LIBGDX Creando o mundo

De Manuais Informática - IES San Clemente.
Ir a la navegación Ir a la búsqueda

UNIDADE 2: Creando o mundo

O fondo de pantalla

Para empezar com algo fácil imos poñer o fondo de pantalla ó noso xogo. O gráfico xa o tedes no cartafol xa que viña na tarefa 2.3 co nome LIBGDX_itin1_fondoxogo.jpg.

Exercicio proposto: Debuxade o gráfico do fondo.



Solución. Código da clase RendererXogo
Obxectivo: Debuxar o fondo do xogo.

 1         .............
 2 	private void debuxarFondo(){
 3 		spritebatch.draw(AssetsXogo.textureFondo,
 4                                  0,0,Mundo.TAMANO_MUNDO_ANCHO,Mundo.TAMANO_MUNDO_ALTO);
 5 	}
 6         .............
 7         public void render(float delta) {
 8 		Gdx.gl.glClearColor(0, 0, 0, 1);
 9 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
10 
11 		spritebatch.begin();
12 		
13 			debuxarFondo();
14 		
15 			debuxarAlien();
16 			debuxarNave();
17 			
18 			debuxarCoches();
19 		
20 		spritebatch.end();
21 		
22 		if (debugger) {
23 			debugger();
24 		}
25         }
26         .............

Os inimigos: Elementos móbiles parte I

Nota: Agora entramos mais en temas de programación que do propio framework. Neste punto teremos como límite a imaxinación.


Temos que ter en conta varias consideracións:

  • Á hora de afrontar este tipo de inimigos que desaparecen e aparecen polo lado contrario temos dúas opcións:
  • Eliminar o inimigo de array cando chega ó final e crear un novo.
  • Mover o inimigo de volta á posición inicial.
A segunda opción é máis sinxela. Imos a utilizar esta opción para os coches e para as rochas usaremos a primeira para ver como se eliminan os obxectos do array.
  • Ademais temos que tomar a decisión de se o número de inimigos (coches-autobuses) é sempre o mesmo ou ben o modificamos de forma aleatoria, de tal forma que poden aumentar ou diminuír. Nos imos a escoller a opción máis sinxela. Se algún alumno quere facer a complexa pode facelo.



A forma máis sinxela de crear os inimigos é engadilos un a un na clase Mundo.

 1 public class Mundo {
 2          .............
 3 	 public final static Vector2 TAMANO_COCHES = new Vector2(20,15);
 4 	 public final static Vector2 TAMANO_AUTOBUSES = new Vector2(30,15);
 5 	 public final static Vector2 TAMANO_ROCA = new Vector2(60,60);
 6 	 public final static Vector2 TAMANO_TRONCO = new Vector2(80,40);
 7 	 
 8          .............
 9 	 
10 	 public Mundo(){
11 		 alien = new Alien(new Vector2(100,20), new Vector2(15,15),100);
12 		 nave = new Nave(new Vector2(0,480),new Vector2(40,20),60f);
13 		 
14 		 coches = new Array<ElementoMobil>();
15 		 coches.add(new ElementoMobil(new Vector2(0,345),TAMANO_AUTOBUSES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
16 		 coches.add(new ElementoMobil(new Vector2(70,345),TAMANO_COCHES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
17 		 coches.add(new ElementoMobil(new Vector2(95,345),TAMANO_COCHES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
18 		 coches.add(new ElementoMobil(new Vector2(115,345),TAMANO_COCHES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
19 		 coches.add(new ElementoMobil(new Vector2(140,345),TAMANO_AUTOBUSES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
20 		 coches.add(new ElementoMobil(new Vector2(210,345),TAMANO_AUTOBUSES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
21 		 coches.add(new ElementoMobil(new Vector2(240,345),TAMANO_COCHES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
22 		 coches.add(new ElementoMobil(new Vector2(278,345),TAMANO_COCHES.cpy(),50,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
23 		 
24 		 coches.add(new ElementoMobil(new Vector2(40,380),TAMANO_COCHES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
25 		 coches.add(new ElementoMobil(new Vector2(70,380),TAMANO_COCHES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
26 		 coches.add(new ElementoMobil(new Vector2(105,380),TAMANO_COCHES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
27 		 coches.add(new ElementoMobil(new Vector2(150,380),TAMANO_AUTOBUSES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
28 		 coches.add(new ElementoMobil(new Vector2(180,380),TAMANO_AUTOBUSES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
29 		 coches.add(new ElementoMobil(new Vector2(220,380),TAMANO_COCHES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
30 		 coches.add(new ElementoMobil(new Vector2(265,380),TAMANO_AUTOBUSES.cpy(),35,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
31 		 
32 	 }
33          .............
34 
35 }

Ó principio definimos o tamaño que queremos que teñan os diferentes elementos (pódense cambiar) e despois engadimos ó array de coches un a un cada un dos coches/autobuses que aparece en pantalla.

Fixarse que chamamos á funcion cpy para crear unha copia do vector tamaño e mandala ó constructor.

Esta sería a forma máis sinxela.


Agora temos que controlar que cando o coche chegue ó extremo, este volva ó principio.

Dito código o teremos que poñer na clase ControladorXogo.

Código da clase ControladorXogo
Obxectivo: controlar cando o coche/autobús chega ó extremo.

 1 	private void controlarCoches(float delta){
 2 		
 3 		for(ElementoMobil coche: meuMundo.getCoches()){
 4 			coche.update(delta);
 5 			if (coche.getPosicion().x>=Mundo.TAMANO_MUNDO_ANCHO){
 6 				coche.setPosicion(-40, coche.getPosicion().y);
 7 			}
 8 		}
 9 
10 	}


Agora queda por poñer os coches que veñen en sentido contrario.

Imos engadir ó noso mundo dous liñas de coches:

Código da clase Mundo

                 ...............
		 coches.add(new ElementoMobil(new Vector2(0,400),TAMANO_AUTOBUSES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
		 coches.add(new ElementoMobil(new Vector2(30,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(70,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(95,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(115,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(140,400),TAMANO_AUTOBUSES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
		 coches.add(new ElementoMobil(new Vector2(210,400),TAMANO_AUTOBUSES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
		 coches.add(new ElementoMobil(new Vector2(240,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(278,400),TAMANO_COCHES.cpy(),-45,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
                 ...............
		 coches.add(new ElementoMobil(new Vector2(0,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(70,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
		 coches.add(new ElementoMobil(new Vector2(115,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(140,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
		 coches.add(new ElementoMobil(new Vector2(240,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
		 coches.add(new ElementoMobil(new Vector2(278,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));

                 ...............

Estes coches irán de dereita a esquerda. Como o facemos ?

Temos dous problemas a ter en conta:

  • A parte controladora: xa que agora os coches deben aparecer na parte dereita cando cheguen ó final. O tema do movemento xa está solucionado, xa que se vos fixades, a velocidade dos coches engadidos ó noso mundo E NEGATIVA.
  • A parte visual, xa que teremos que voltear a imaxe.


Parte conntroladora:

Código da clase ControladorXogo
Obxectivo: controlar cando o coche/autobús chega ó extremo esquerdo ou dereito dependendo da velocidade.

 1 	private void controlarCoches(float delta){
 2 		
 3 		for(ElementoMobil coche: meuMundo.getCoches()){
 4 			coche.update(delta);
 5 			if (coche.getVelocidade()>0){	// Vai de esquerda a dereita
 6 				if (coche.getPosicion().x>=Mundo.TAMANO_MUNDO_ANCHO){
 7 					coche.setPosicion(-Mundo.TAMANO_AUTOBUSES.x, coche.getPosicion().y);
 8 				}
 9 			}
10 			else{	// Vai de dereita a esquerda
11 				if (coche.getPosicion().x<=-coche.getTamano().x){
12 					coche.setPosicion(Mundo.TAMANO_MUNDO_ANCHO, coche.getPosicion().y);
13 				}
14 			}
15 	        }
16 	}

Varias consideracións:

  • Se imos de esquerda a dereita, cando chegue ó final (coche.getPosicion().x>=Mundo.TAMANO_MUNDO_ANCHO) o posicionamos na parte esquerda da pantalla pero fora da visión do xogador, para facer que vaia aparecendo. Dos dous elementos móbiles, o máis grande é o autobús e por iso os poñemos nesa posición en negativo (para que quede fora da pantalla).
  • Se imos de dereita a esquerda temos que ter en conta que o coche é máis pequeno que o autobús e polo tanto cando o trasladamos á posición inicial (á parte dereita) temos que movelo un pouco máis a dereita que o autobús xa que se non en cada pasada o coche se irá achegando máis ó autobús.

O podedes probar có código anterior.

Para solucionalo:
Código da clase ControladorXogo
Obxectivo: controlar cando o coche/autobús chega ó extremo esquerdo ou dereito dependendo da velocidade.

 1 	private void controlarCoches(float delta){
 2 		
 3 		for(ElementoMobil coche: meuMundo.getCoches()){
 4 			coche.update(delta);
 5 			if (coche.getVelocidade()>0){	// Vai de esquerda a dereita
 6 				if (coche.getPosicion().x>=Mundo.TAMANO_MUNDO_ANCHO){
 7 					coche.setPosicion(-Mundo.TAMANO_AUTOBUSES.x, coche.getPosicion().y);
 8 				}
 9 			}
10 			else{	// Vai de dereita a esquerda
11 				if (coche.getPosicion().x<=-coche.getTamano().x){
12 					if (coche.getTipo()==ElementoMobil.TIPOS_ELEMENTOS.COCHE)	// E un coche enton necesitamos situalo un pouco a dereita se non vai pisando o autobus
13 						coche.setPosicion(Mundo.TAMANO_MUNDO_ANCHO+Mundo.TAMANO_AUTOBUSES.x-Mundo.TAMANO_COCHES.x, coche.getPosicion().y);
14 					else
15 						coche.setPosicion(Mundo.TAMANO_MUNDO_ANCHO, coche.getPosicion().y);
16 				}
17 			}
18 		}
19 
20 	}


Parte de renderizado: Para solucionar este problema temos varias aproximacións:

  • Ter outra textura cargada na clase AssetsXogo que sexa a mesma pero volteada.
  • Utilizar a clase TextureRegion. Esta clase a volveremos a ver na sección de animación en programación avanzada.
Dita clase posúe o método flip que serve para 'voltear' a imaxe nun ou nos dous eixes x,y.
Un exemplo sería:
TextureRegion texreg = new TextureRegion(textura);
texreg.flip(true, false);
spritebatch.draw(texreg,coche.getPosicion().x,coche.getPosicion().y,coche.getTamano().x,coche.getTamano().y);
Nota: Lembrar que os new´s debe intentar evitarse dentro do render. É mellor ten un único new cando instanciemos a clase e chamar ó método setRegion e asinarlle a textura que queiramos rotar.
  • Poñendo unha velocidade negativa. Desta forma os coches se moverán de dereita a esquerda. Pero temos que ter en conta que desta forma a posición 'visual' dos coches / autobuses non coinciden coa posición 'real' no noso mundo. O podemos comprobar se activamos o debuger na clase RendererXogo e debuxamos os coches.

Código da clase RendererXogo
Obxectivo: Debuxar os coches que veñen de dereita a esquerda.

 1 	private void debuxarCoches(){
 2 		Texture textura=null;
 3 
 4 		for (ElementoMobil coche : meumundo.getCoches()){
 5 			switch(coche.getTipo()){
 6 				case COCHE:
 7 					textura = AssetsXogo.textureCoche;
 8 					break;
 9 				default:			
10 					textura = AssetsXogo.textureAutobus;
11 					break;
12 			}
13 			if (coche.getVelocidade()<0){
14 				spritebatch.draw(textura,coche.getPosicion().x,coche.getPosicion().y,-coche.getTamano().x,coche.getTamano().y);
15 			}
16 			else{
17 				spritebatch.draw(textura,coche.getPosicion().x,coche.getPosicion().y,coche.getTamano().x,coche.getTamano().y);
18 			}
19 		
20 			
21 		}
22 	}


 1     private void debugger(){
 2            
 3             shaperender.begin(ShapeType.Line);
 4             shaperender.setColor(Color.BLUE);
 5             for (ElementoMobil coche : meumundo.getCoches()){
 6                 shaperender.rect(coche.getPosicion().x,coche.getPosicion().y,coche.getTamano().x,coche.getTamano().y);
 7             }
 8             shaperender.end();
 9            
10     }
Dará como resultado isto:
LIBGDX UD2 8 mundo 2.jpg

Para solucionalo só temos que desprazar o ancho do coche/autobús á súa posición.

Código da clase RendererXogo
Obxectivo: Facer coincidir a posición real coa posición visual.

 1 	private void debuxarCoches(){
 2 		Texture textura=null;
 3 
 4 		for (ElementoMobil coche : meumundo.getCoches()){
 5 			switch(coche.getTipo()){
 6 				case COCHE:
 7 					textura = AssetsXogo.textureCoche;
 8 					break;
 9 				default:			
10 					textura = AssetsXogo.textureAutobus;
11 					break;
12 			}
13 			if (coche.getVelocidade()<0){
14 				spritebatch.draw(textura,coche.getPosicion().x+coche.getTamano().x,coche.getPosicion().y,-coche.getTamano().x,coche.getTamano().y);
15 			}
16 			else{
17 				spritebatch.draw(textura,coche.getPosicion().x,coche.getPosicion().y,coche.getTamano().x,coche.getTamano().y);
18 			}
19 		
20 			
21 		}
22 	}

Fixarse como na liña 14 engadimos á posición do coche/autobús o seu tamaño.
NOTA:No desenvolvemento do xogo os alumnos poden escoller a solución que crean máis conveniente.

Engadimos agora a outra liña de coches que faltaba:

Código da clase Mundo

1                  coches.add(new ElementoMobil(new Vector2(0,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
2 		 coches.add(new ElementoMobil(new Vector2(70,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
3 		 coches.add(new ElementoMobil(new Vector2(115,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
4 		 coches.add(new ElementoMobil(new Vector2(140,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));
5 		 coches.add(new ElementoMobil(new Vector2(240,365),TAMANO_COCHES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.COCHE));
6 		 coches.add(new ElementoMobil(new Vector2(278,365),TAMANO_AUTOBUSES.cpy(),-65,ElementoMobil.TIPOS_ELEMENTOS.AUTOBUS));

Loxicamente podedes engadir ou quitar coches para facelo máis fácil ou máis complicado :).


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


Os inimigos: Elementos móbiles parte II

Neste punto teredes movéndose os coches e as rochas polo voso xogo. Agora imos facer unha pequena modificación que vai consistir en eliminar os elementos móbiles do array e volver a engadilos. Poderíamos engadilos nunha posición aleatoria para facelo máis complicado e tamén poderíamos modificar a velocidade. Quen quera facelo pode (xa comentado como solución alternativa na tarefa 2.6). Para facelo máis sinxelo na explicación que ven a continuación só imos traballar con tres troncos, un por cada fila.


O proceso é o mesmo que nos coches e rochas. Só temos que cambiar ó método da clase ControladorXogo.

Código da clase Mundo
Obxectivo: creamos os troncos.

 1          ..............
 2 	 private Array<ElementoMobil>troncos;
 3 	 public Mundo(){
 4                  ..............
 5 		 troncos = new Array<ElementoMobil>();
 6 		 troncos.add(new ElementoMobil(new Vector2(100,220),TAMANO_TRONCO.cpy(),-50,ElementoMobil.TIPOS_ELEMENTOS.TRONCO));
 7 		 troncos.add(new ElementoMobil(new Vector2(60,260),TAMANO_TRONCO.cpy(),40,ElementoMobil.TIPOS_ELEMENTOS.TRONCO));
 8 		 troncos.add(new ElementoMobil(new Vector2(150,300),TAMANO_TRONCO.cpy(),-70,ElementoMobil.TIPOS_ELEMENTOS.TRONCO));
 9                  ..............
10          }
11 	public Array<ElementoMobil> getTroncos() {
12 		return troncos;
13 	}
14 
15          ..............


Código da clase RendererXogo
Obxectivo: debuxamos os troncos.

 1          ..............
 2 	private void debuxarTroncos(){
 3 		for (ElementoMobil tronco : meumundo.getTroncos()){
 4 			spritebatch.draw(AssetsXogo.textureTronco,tronco.getPosicion().x,tronco.getPosicion().y,tronco.getTamano().x,tronco.getTamano().y);
 5 		}
 6 
 7 	}
 8          ..............
 9 
10          ..............
11     public void render(float delta) {
12 		Gdx.gl.glClearColor(0, 0, 0, 1);
13 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
14 
15 		spritebatch.begin();
16 		
17 			debuxarFondo();
18 		
19 			debuxarAlien();
20 			debuxarNave();
21 			
22 			debuxarCoches();
23 			debuxarRochas();
24 			debuxarTroncos();
25 			
26 		
27 		spritebatch.end();
28                 ..............
29     }


Agora chega a diferenza que é eliminar os elementos do array na clase ControladorXogo cando as rochas cheguen os límites.

Código da clase ControladorXogo
Obxectivo: actualiza e elimina/creo os troncos ó chegar ós limites.

 1         ...............
 2 	private void controlarTroncos(float delta){
 3 		for(ElementoMobil tronco: meuMundo.getTroncos()){
 4 			tronco.update(delta);
 5 			if (tronco.getPosicion().x<-Mundo.TAMANO_TRONCO.x){
 6 				meuMundo.getTroncos().add(new ElementoMobil(new Vector2(MathUtils.random(Mundo.TAMANO_MUNDO_ANCHO, Mundo.TAMANO_MUNDO_ANCHO+Mundo.TAMANO_TRONCO.x),	tronco.getPosicion().y),Mundo.TAMANO_TRONCO.cpy(),tronco.getVelocidade(),ElementoMobil.TIPOS_ELEMENTOS.TRONCO));
 7 				meuMundo.getTroncos().removeValue(tronco, true);
 8 
 9 			}
10 			if (tronco.getPosicion().x>Mundo.TAMANO_MUNDO_ANCHO){
11 				meuMundo.getTroncos().add(new ElementoMobil(new Vector2(MathUtils.random(-2*Mundo.TAMANO_TRONCO.x,-Mundo.TAMANO_TRONCO.x),
12 							tronco.getPosicion().y),Mundo.TAMANO_TRONCO.cpy(),tronco.getVelocidade(),ElementoMobil.TIPOS_ELEMENTOS.TRONCO));
13 				meuMundo.getTroncos().removeValue(tronco, true);
14 			}
15 			
16 		}
17 		
18 		
19 	}
20 	public void update(float delta) {
21 
22 		controlarCoches(delta);
23 		controlarRochas(delta);
24 		controlarTroncos(delta);
25 
26 	}
27         ...............

Comentamos o código:

  • Liña 5: comprobamos se a rocha alcanza o límite (ven de dereita a esquerda).
  • Liña 6: se é o caso, creamos unha nova rocha antes de eliminala xa que necesitamos darlle a posición Y que ten a rocha e tamén a velocidade. Neste exemplo non se xera unha velocidade aleatoria quedando como posible exercicio. Como se ve, cando fai o new da posición temos o seguinte código:
new Vector2(MathUtils.random(Mundo.TAMANO_MUNDO_ANCHO, Mundo.TAMANO_MUNDO_ANCHO+Mundo.TAMANO_TRONCO.x)
Isto xera un número aleatorio entre o tamano de mundo no ancho e o mesmo tamano máis o ancho do tronco. Desta forma xeramos unha posición aleatoria no eixe x.
  • Liñas 10-12: o mesmo pero para o caso de que a rocha vaia de esquerda a dereita.

Lembrade que xa vimos como eliminar un elemento do array.


A nave espacial

Chega o momento de mover a nosa nave.

Como sempre, os pasos son:

  • Cargar a textura na clase AssetsXogo.
  • Crear a clase que derive de Personaxe e que terá toda a información da nave. Chamarémoslle Nave.
  • Crear o obxecto nave na clase Mundo e o método get asociado.
  • Debuxar a nave na clase Renderer.
  • Controlar a nave na clase ControladorXogo. Aquí imos facer unha pequena trampa (é optativo facelo) e vou pasar o código que fai que a nave se pare en cada plataforma á clase Nave ó seu método update.


Empecemos:

A primeira parte xa está feita da tarefa 2.3.


Creamos a clase que deriva de Personaxe. O facemos no paquete modelo.

Código da clase Nave

 1 public class Nave extends Personaxe {
 2 
 3 	public Nave(Vector2 posicion, Vector2 tamano, float velocidade_max) {
 4 		super(posicion, tamano, velocidade_max);
 5 		velocidade=velocidade_max;
 6 	}
 7 
 8 	@Override
 9 	public void update(float delta) {
10 			setPosicion(getPosicion().x+delta*velocidade, getPosicion().y);
11 		
12 			// Se chega ó final do recorrido cambiamos de dirección
13 			if (posicion.x >=Mundo.TAMANO_MUNDO_ANCHO-getTamano().x){
14 				setPosicion(Mundo.TAMANO_MUNDO_ANCHO-getTamano().x,getPosicion().y);
15 				velocidade=-1*velocidade;
16 			} else if (posicion.x<=0) {
17 				setPosicion(0,getPosicion().y);
18 				velocidade=-1*velocidade;
19 			}
20 	}
21 
22 }

Varios comentarios:

  • Liña 5: a nave dende o comenzo está movéndose, polo que dende o principio ten unha velocidade.
  • Liñas 13-19: cando a nave chega os límites temos que facer que se mova en dirección contraria. O conseguimos multiplicando por -1 a súa velocidade.
Imaxinemos que a velocidade da nave é positiva, por exemplo 50. Isto quere dicir que a nave vai de esquerda a dereita. Cando chegue ó final da pantalla multiplicamos por -1 e teremos unha velocidade de -50 e se moverá de dereita a esquerda. O mesmo na outra dirección.
Por que temos asinada unha posición nas liñas 14 e 17 ? Imaxinemos o caso que a nave vai de dereita a esquerda e chega a -0.8f. Lembrade que en cada iteración restamos delta * velocidade e case nunca vai dar 0 exacto. Por iso o límite sempre ten que estar feito con >= ou <=. Neste caso cambiaríamos de velocidade a positivo e imaxinemos que a nave se move a -0.3f. Como vemos segue sendo negativa e polo tanto volvería a entrar no if do límite alcanzado. Volvería a cambiar de velocidade e volvería a ir cara a esquerda.


Crear o obxecto nave na clase Mundo e o método get asociado. Xa feito anteriormente (tarefa 2.4).


Debuxar a nave na clase Renderer. Xa feito anteriormente (tarefa 2.4).


Controlar a nave na clase ControladorXogo

Para mover a nave só temos que chamar ó método update.

Código da clase ControladorXogo
Obxectivo: mover a nave.

 1         ..............
 2 	private void controlarNave(float delta){
 3 		meuMundo.getNave().update(delta);
 4 	}
 5 
 6 	public void update(float delta) {
 7 
 8 		controlarCoches(delta);
 9 		controlarRochas(delta);
10 		controlarTroncos(delta);
11 		
12 		controlarNave(delta);
13 
14 	}
15         ..............


Podedes probar como a nave se move nos límites da pantalla.


Agora falta que a nave se quede parada, digamos 3 segundos en cada unha das plataformas. Vos atrevedes a facelo ?

Pistas:

  • As posición en que debe parar a nave son: entre 33-35; entre 133-135; entre 227-229 (lembrar que non podemos poñer unha condición de 'posición nave = 33' xa que nunca vai dar o número exacto.
  • A idea é que cando a nave chegue a algunha destas posicións paremos a nave. Como ? Temos varias opcións, poñendo a velocidade a 0 ou utilizar unha variable booleana que indique cando debe estar parada. Cando a variable valga true facemos que non entre no código que que cambia a posición en función da velocidade.
  • Cando saibamos que debe estar parada, poñeremos en marcha un cronómetro (utilizar delta) e cando chegue a 3 segundos (ou pode ir dende 3 a 0) debemos de cambiar a variable booleana para que xa se poda mover a nave.





Posible solución:

Código da clase Nave
Obxectivo: facer que a nave se pare 3 segundos en cada plataforma.

 1 public class Nave extends Personaxe {
 2 
 3 	private final int TEMPO_MOVENDOSE=3;
 4 	/**
 5 	 * Leva o tempo que está parado. Cando chegue a 0 volve a moverse.
 6 	 */
 7 	private float tempo;
 8 	
 9 	private boolean parado;
10 	
11 	public Nave(Vector2 posicion, Vector2 tamano, float velocidade_max) {
12 		super(posicion, tamano, velocidade_max);
13 		// TODO Auto-generated constructor stub
14 		velocidade=velocidade_max;
15 		parado=false;
16 		tempo=0;
17 	}
18 
19 	@Override
20 	public void update(float delta) {
21 		// TODO Auto-generated method stub
22 		if ((posicion.x > 33 && posicion.x < 35) ||
23 			(posicion.x > 133 && posicion.x < 135) ||
24 			(posicion.x > 227 && posicion.x < 229))
25 		{
26 			parado=true;
27 		}
28 		if (parado){
29 			tempo+=delta;
30 			if (tempo > TEMPO_MOVENDOSE){
31 				tempo=0;
32 				parado=false;
33 			}
34 		}
35 		if (!parado){
36 			setPosicion(getPosicion().x+delta*velocidade, getPosicion().y);
37 		
38 			// Se chega ó final do recorrido cambiamos de dirección
39 			if (posicion.x >=Mundo.TAMANO_MUNDO_ANCHO-getTamano().x){
40 				setPosicion(Mundo.TAMANO_MUNDO_ANCHO-getTamano().x,getPosicion().y);
41 				velocidade=-1*velocidade;
42 			} else if (posicion.x<=0) {
43 				setPosicion(0,getPosicion().y);
44 				velocidade=-1*velocidade;
45 			}
46 		}
47 	}
48 
49 }



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