LIBGDX Fontes

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

UNIDADE 2: Fontes

Información da wiki: https://github.com/libgdx/libgdx/wiki/Bitmap-fonts

Normalmente nos xogos imos ter que escribir texto na pantalla.

Para facelo imos ter que utilizar a clase BitMapFont.


Empecemos indicando que é un BitMap. Para nos un BitMap é unha imaxe que representa unha letra. Dita letra (imaxe) pode ser escalada (aumentar ou reducir de tamaño).

Dependendo do tamaño inicial da letra, este escalado pode dar lugar a letras con dentes de serra. O ideal para que isto non suceda é ter o tamaño de letra igual de grande que na visualización para non ter que facer escalado de 'aumento'.

Inconveniente que teñen os BitMap: o tamaño que ocupan en disco. Se temos un xogo cunha única fonte ó mellor non é problema, pero se temos moitos tipos de fonte e estamos en Android si pode dar lugar a inconvenientes.

Para solucionalo mellor utilizar as fontes TrueType xa que ocupan moito menos espazo. Para aprender a utilizar este tipo de fontes podedes visitar este enlace: https://github.com/libgdx/libgdx/wiki/Gdx-freetype


Neste itinerario imos utilizar o BitMapFont por defecto que ten como inconveniente que non escala moi ben e pode dar lugar a texto cun aspecto malo (dentes de serra).

O proceso para utilizalas é moi sinxelo.


Preparación: Agora ides facer unha copia da clase RendererXogo, xa que imos modificala para amosarvos como se utilizan os BitMapFont. Premede co rato sobre a clase, botón dereito e escollede a opción Copy. Despois repetides a operación pero escolledes a opción Paste. Vos preguntará un nome para a clase. Indicade UD2_6_RendererXogo.

Código da clase UD2_6_RendererXogo
Obxectivo: utilizar BitMapFont.

 1 import com.badlogic.gdx.Gdx;
 2 import com.badlogic.gdx.graphics.Color;
 3 import com.badlogic.gdx.graphics.GL20;
 4 import com.badlogic.gdx.graphics.OrthographicCamera;
 5 import com.badlogic.gdx.graphics.g2d.BitmapFont;
 6 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
 7 import com.plategaxogo2d.modelo.Mundo;
 8 
 9 /*
10  * Comprobamos como utilizar as BitMapFont.
11  */
12 
13 public class UD2_6_RendererXogo {
14 
15     private OrthographicCamera camara2d;
16     private SpriteBatch spritebatch;
17     
18 
19     public UD2_6_RendererXogo(Mundo mundo) {
20 
21     	camara2d = new OrthographicCamera();
22         spritebatch = new SpriteBatch();
23         
24     }
25 
26     
27 	
28 	public OrthographicCamera getCamara2d(){
29 		return camara2d;
30 	}
31 	
32     /**
33      * Debuxa todos os elementos graficos da pantalla
34      *
35      * @param delta
36      *            : tempo que pasa entre un frame e o seguinte.
37      */
38     public void render(float delta) {
39 		Gdx.gl.glClearColor(0, 0, 0, 1);
40 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
41 
42 		
43 		spritebatch.begin();
44 		
45 		
46 		spritebatch.end();
47 		
48     }
49 
50 
51 
52     public void resize(int width, int height) {
53 
54 		camara2d.setToOrtho(false, Mundo.TAMANO_MUNDO_ANCHO,
55 				Mundo.TAMANO_MUNDO_ALTO);
56 		camara2d.update();
57 
58 		spritebatch.setProjectionMatrix(camara2d.combined);
59 		
60 
61     }
62 
63     public void dispose() {
64     	spritebatch.dispose();
65     }
66 
67 
68 }


Modificade a clase PantallaXogo para que chame a esta clase. Ó iniciar o xogo aparece a pantalla de presentación. Debedes premer Novo Xogo para que chame a esta pantalla.


Clase BitMapFont. Por defecto utiliza unha fonte que ven integrada no jar do Libgdx. Ten un tamaño de 15 puntos e é Arial.

Métodos máis importantes:

A partires del podemos modificar a escala da letra:
  • scale(float amount): Cambia a escala da fonte de forma relativa á escala actual.
  • setScale(float scaleXY): Escala a fonte en ancho e alto á vez. Este método está sobrecargado e permite escalar de forma independente en cada eixe. Tamén comentar que dependendo da relación da aspecto do noso xogo, as letras poden saír deformadas por defecto tendo que escalas nos para unha visualización correcta.



Código da clase UD2_6_RendererXogo
Obxectivo: Exemplo de uso da clase BitMapFont.

 1 public class UD2_6_RendererXogo {
 2 
 3     private OrthographicCamera camara2d;
 4     private SpriteBatch spritebatch;
 5     private BitmapFont bitMapFont;
 6     
 7 
 8     public UD2_6_RendererXogo(Mundo mundo) {
 9 
10     	camara2d = new OrthographicCamera();
11         spritebatch = new SpriteBatch();
12         
13         bitMapFont = new BitmapFont();
14     }
15 
16     
17 	
18 	public OrthographicCamera getCamara2d(){
19 		return camara2d;
20 	}
21 	
22     /**
23      * Debuxa todos os elementos graficos da pantalla
24      *
25      * @param delta
26      *            : tempo que pasa entre un frame e o seguinte.
27      */
28     public void render(float delta) {
29 		Gdx.gl.glClearColor(0, 0, 0, 1);
30 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
31 
32 		
33 		spritebatch.begin();
34 		
35         bitMapFont.setColor(Color.RED);
36         bitMapFont.setScale(10);
37 		bitMapFont.draw(spritebatch, "TEXTO ESCALADO A 10 VECES O SEU TAMAÑO", 0, 250);
38 
39         bitMapFont.setColor(Color.YELLOW);
40         bitMapFont.getData().setScale(0.5f, 2);
41 		bitMapFont.draw(spritebatch, "TEXTO ESCALADO", 0, 350);
42 
43 		spritebatch.end();
44 		
45     }
46 
47 
48 
49     public void resize(int width, int height) {
50 
51 		camara2d.setToOrtho(false, Mundo.TAMANO_MUNDO_ANCHO,
52 				Mundo.TAMANO_MUNDO_ALTO);
53 		camara2d.update();
54 
55 		spritebatch.setProjectionMatrix(camara2d.combined);
56 		
57 
58     }
59 
60     public void dispose() {
61     	bitMapFont.dispose();
62     	spritebatch.dispose();
63     }
64 
65 
66 }



Dará como resultado isto:

LIBGDX UD2 12 Fontes 1.jpg


Nota: Loxicamente se a escala ou cor no van modificarse nunca é conveniente levar estas ordes ó constructor para só se executen unha vez.


Outro factor a ter en conta cando manexamos cadeas é o de optimizar o uso da memoria. Cando queremos concatenar dúas cadeas normalmente faríamos isto:

1  		String cad1 = "CAD1";
2  		String cad2 = "CAD2";
3  		
4  		String cad3 = cad1 + cad2;

Esta forma de concatenar ten como inconveniente que crear unha nova zona de memoria para a nova cadea. Se o facemos dentro do método render, estaremos creando novas cadeas continuamente. Para evitalo debemos facer uso da clase StringBuilder.

Tedes unha explicación do seu uso neste enlace.

Un exemplo de uso:

Código da clase UD2_6_RendererXogo
Obxectivo: Usa a clase StringBuilder para crear novas cadeas e concatenar.

 1 public class UD2_6_RendererXogo {
 2 
 3     private OrthographicCamera camara2d;
 4     private SpriteBatch spritebatch;
 5     private BitmapFont bitMapFont;
 6     private StringBuilder sbuffer;
 7     
 8 
 9     public UD2_6_RendererXogo(Mundo mundo) {
10 
11     	camara2d = new OrthographicCamera();
12         spritebatch = new SpriteBatch();
13         
14         bitMapFont = new BitmapFont();
15         sbuffer = new StringBuilder();
16         sbuffer.append("TEXTO ALEAOTORIO:");
17     }
18 
19     
20 	
21 	public OrthographicCamera getCamara2d(){
22 		return camara2d;
23 	}
24 	
25     /**
26      * Debuxa todos os elementos graficos da pantalla
27      *
28      * @param delta
29      *            : tempo que pasa entre un frame e o seguinte.
30      */
31     public void render(float delta) {
32 		Gdx.gl.glClearColor(0, 0, 0, 1);
33 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
34 
35 		
36 		spritebatch.begin();
37 		
38                 bitMapFont.setColor(Color.RED);
39                 bitMapFont.setScale(10);
40 		bitMapFont.draw(spritebatch, "TEXTO ESCALADO A 10 VECES O SEU TAMAÑO", 0, 250);
41 
42                 bitMapFont.setColor(Color.YELLOW);
43                 bitMapFont.setScale(0.5f, 2);
44 		bitMapFont.draw(spritebatch, "TEXTO ESCALADO", 0, 350);
45 
46                 bitMapFont.setColor(Color.WHITE);
47         
48                 if (sbuffer.length()>50) {
49                    sbuffer.setLength(0);  	// Borramos
50                    sbuffer.append("TEXTO ALEATORIO:");
51                 }
52                 sbuffer.append(MathUtils.random(9));
53          	bitMapFont.draw(spritebatch, sbuffer, 0, 50);
54 
55 		spritebatch.end();
56 		
57     }
58 
59 
60 
61     public void resize(int width, int height) {
62 
63 		camara2d.setToOrtho(false, Mundo.TAMANO_MUNDO_ANCHO,
64 				Mundo.TAMANO_MUNDO_ALTO);
65 		camara2d.update();
66 
67 		spritebatch.setProjectionMatrix(camara2d.combined);
68 		
69 
70     }
71 
72     public void dispose() {
73     	bitMapFont.dispose();
74     	spritebatch.dispose();
75     }
76 
77 
78 }


Nota: Volvede a modificar á clase PantallaXogo para que chame á clase RendererXogo.


Engadindo un cronómetro ó noso xogo

Imos engadir un tempo ó noso xogo, de tal forma que ó rematar iremos á pantalla de marcadores.


Para facelo imos definir unha constante de clase que gardará o tempo inicial (serán 120 segundos) e outra propiedade de clase de nome cronometro que, como di o seu nome, será un cronómetro :) .

Código da clase Mundo
Obxectivo: definimos un cronómetro.

 1 public class Mundo {
 2 
 3         ..................
 4 	 private final static int TEMPO_INICIAL=120;
 5 	 private float cronometro;
 6 
 7         ..................
 8         public Mundo(){
 9        	   alien = new Alien(new Vector2(100,20), new Vector2(15,15),100);
10     	   nave = new Nave(new Vector2(0,480),new Vector2(40,20),60);
11     	
12     	   vehiculos = new Elementos(1.5f,3f,20);
13     	   troncos = new Elementos(2f,5f,6);
14     	   rocas = new Elementos(2f,5f,3);
15     	
16     	   cronometro=TEMPO_INICIAL;
17     	
18         }
19 
20 	public int getCronometro() {
21 		return (int)cronometro;
22 	}
23 
24 	public void setCronometro(float cronometro) {
25 		this.cronometro = cronometro;
26 	}
27 	
28 	public void updateCronometro(float delta){
29 		cronometro-=delta;
30 	}
31 	
32         ..................
33 }

Agora só temos que restar delta a cronometro no controlador do xogo.

Código da clase ControladorXogo
Obxectivo: actualizamos o cronómetro.

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



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




Tarefas avanzadas



TAREFA AVANZADA: Esta parte está asociada á realización dunha tarefa avanzada. Fontes Avanzadas..




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