Cuando definimos las frutas que puede recolectar nuestro personaje, nos quedo pendiente el tema del puntaje. Al recoger cada fruta se debe sumar un puntaje, el cual debe mostrarse en algún lugar de la pantalla.
Comenzaremos con lo más básico, modificando lo que tenemos escrito para que llegue cuenta de los puntos; haremos algunos cambios sobre el método updateGame(), particularmente dentro del bloque de código que determina si se recoge la fruta o no. Definimos cuatro variables que nos van a ayudar en el proceso:
private boolean winCredits = false;
private int numberWinCredits = 0;
private int credits = 0;
public void updateGame() {
/** resto del codigo **/
if(isHorizontalColision(player,fruit,-12)) {
if(!fruit.isCollected()) {
winCredits = true;
numberWinCredits = fruit.getCreditsValue();
credits = credits + fruit.getCreditsValue();
fruit.setCollected(true);
}
}
}
La idea es la siguiente: tendremos el puntaje en la esquina superior derecha de la ventana, solo actualizaremos la imagen del puntaje cada vez que se modifique, para ello utilizamos la variable updateCredits; winCredits nos permite determinar si mostramos el efecto de que el jugador gano puntos. Credits acumula la cantidad de puntos total desde que comenzo la partida y numberWinCredits los puntos ganados en ese momento, en función de la fruta recolectada.
Para mostrar el puntaje acumulado, necesitamos crear una clase que construya números desde el sprite de letras/números; esto permite mantener mas o menos la misma lógica que venimos aplicando y no depender de si tenemos instalada alguna fuente o no.
Crearemos una clase llamada Credits:
package gsampallo;
import java.awt.Dimension;
import java.awt.Point;
import javax.imageio.*;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
public class Credits {
public int width = 16;
public int height = 10;
public Credits() {
loadImages();
}
private BufferedImage imageCredits;
private void loadImages() {
try {
imageCredits = ImageIO.read(new File("image/Menu/Text/Text (White) (8x10).png"));
} catch (Exception e) {
System.err.println("No se pudieron cargar imagenes de Credits");
System.err.println(e.getMessage());
}
}
}
Hasta este punto la clase Credits no es muy diferente de las que veníamos definiendo, salvo que no implementa la interfaz Element.
Si estudiamos la imagen que carga, vemos que podemos acceder a cada uno de los caracteres de la misma manera que lo hacemos con los sprites de las animaciones.
De modo que si necesitamos el nro. 1580; el eje Y se mantendrá fijo en 3, e iremos modificando x, donde x=1 para 1, x=5 para 5 y asi; nos resulta muy sencillo.
Incorporaremos un nuevo método a Credits, llamado getPlusOne() que nos proveerá de una imagen para el efecto de cuando el jugador recolecta una fruta:
public BufferedImage getPlusOne() {
return imageCredits.getSubimage(8,30, 8,10);
}
public BufferedImage getCreditsNumber(int nro) {
return imageCredits.getSubimage(nro*8,30,8,10);
}
Simplemente devuelve una imagen con el símbolo de la suma (+). No será necesario el punto (x,y) puesto que lo haremos relativo a la posición del jugador; para ello modificaremos el método RunnerOne.paint():
private int showCreditNumber = 0;
public void paint(Graphics g) {
/** resto del codigo **/
if(winCredits) {
if(showCreditNumber < 3) {
g.drawImage(showCredits.getCreditsNumber(numberWinCredits),player.getX()+player.getWidth(),player.getY()-3,null);
showCreditNumber++;
} else {
showCreditNumber = 0;
winCredits = false;
}
}
}
Si compilamos y ejecutamos obtendremos el siguiente efecto:
Aún nos queda mostrar el puntaje total en la esquina superior izquierda de la pantalla; para ello necesitamos incorporar un nuevo metodo en Credits:
private BufferedImage imageScore;
public void updateScore(int score) {
String strCredits = ""+score;
char[] listN = strCredits.toCharArray();
imageScore = new BufferedImage(listN.length*width,height,imageCredits.getType());
Graphics g = imageScore.createGraphics();
for(int i=0; i<listN.length; i++) {
int n = ((int)listN[i]) - 48;
g.drawImage(getCreditsNumber(n),i*width,0,null);
}
}
public BufferedImage getScore() {
return imageScore;
}
updateScore() toma la cantidad de créditos ganamos, lo convierte a un array de chars desde el cual obtiene cada una de las imágenes de los números, y las une en una nueva imagen; este proceso lo hacemos solamente cuando se modifica el credito. getScore() devuelve la imagen que formo anteriormente.
En el método RunnerOne.updateGame() incorporamos las siguientes lineas:
public void updateGame() {
/** resto del codigo **/
if(isHorizontalColision(player,fruit,-12)) {
if(!fruit.isCollected()) {
winCredits = true;
numberWinCredits = fruit.getCreditsValue();
credits = credits + fruit.getCreditsValue();
showCredits.updateScore(credits);
fruit.setCollected(true);
}
}
}
También debemos actualizar RunnerOne.paint() para que dibuje el puntaje, nos conviene hacerlo inmediatamente después de graficar el background:
public void paint(Graphics g) {
/** resto del codigo **/
g.drawImage(showCredits.getScore(), 20,50,null);
}
No olvidemos incovar a updateScore(0) en el constructor de Credits, puesto que al comienzo del juego la imagen de los creditos será nula.