LIBGDX Creando o mundo

De MediaWiki
Saltar a: navegación, buscar

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 -- (2015).