Agregando puntuación y aumentando la velocidad

Todo juego necesita una medida de logro o éxito. En nuestro caso incluiremos en el rincón izquierdo de la pantalla nuestra puntuación que no será más que la cantidad de veces que logramos pegarle a la pelota con la raqueta. Por otro lado el juego debería ser cada vez más difícil para no matar de aburrimiento al jugador. Para esto aumentaremos la velocidad del juego cada vez que rebote la pelota en la raqueta.

Los objetos móviles del juego son la pelota y la raqueta. Modificando la velocidad de movimiento de estos dos objetos modificaremos la velocidad del juego. Vamos a incluir una propiedad llamada speed en la clase Game para mantener la velocidad del juego. La propiedad speed será inicialmente 1 e irá incrementándose cada vez que le demos a la pelota con la raqueta.

Para la puntuación necesitaríamos otra propiedad a incrementar cada vez que golpeemos la pelota. En vez de crear una nueva propiedad se me ocurrió reutilizar speed. El único inconveniente es que las puntuaciones suelen iniciarse en 0 y no en 1 como speed. La solución que se me ocurrió fue agregar un método getScore() que retorne el valor de speed menos uno.

	private int getScore() {
		return speed - 1;
	}

Veamos las modificaciones hechas en la clase Game:

package com.edu4java.minitennis8;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Game extends JPanel {

	Ball ball = new Ball(this);
	Racquet racquet = new Racquet(this);
	int speed = 1;

	private int getScore() {
		return speed - 1;
	}

	public Game() {
		addKeyListener(new KeyListener() {
			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				racquet.keyReleased(e);
			}

			@Override
			public void keyPressed(KeyEvent e) {
				racquet.keyPressed(e);
			}
		});
		setFocusable(true);
		Sound.BACK.loop();
	}

	private void move() {
		ball.move();
		racquet.move();
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		ball.paint(g2d);
		racquet.paint(g2d);

		g2d.setColor(Color.GRAY);
		g2d.setFont(new Font("Verdana", Font.BOLD, 30));
		g2d.drawString(String.valueOf(getScore()), 10, 30);
	}

	public void gameOver() {
		Sound.BACK.stop();
		Sound.GAMEOVER.play();
		JOptionPane.showMessageDialog(this, "your score is: " + getScore(),
				"Game Over", JOptionPane.YES_NO_OPTION);
		System.exit(ABORT);
	}

	public static void main(String[] args) throws InterruptedException {
		JFrame frame = new JFrame("Mini Tennis");
		Game game = new Game();
		frame.add(game);
		frame.setSize(300, 400);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		while (true) {
			game.move();
			game.repaint();
			Thread.sleep(10);
		}
	}
}

Para pintar la puntuación en el rincón superior izquierdo al final del método paint he agregado:

		g2d.setColor(Color.GRAY);
		g2d.setFont(new Font("Verdana", Font.BOLD, 30));
		g2d.drawString(String.valueOf(getScore()), 10, 30);

En la primera línea elegimos el color gris, en la segunda línea el tipo de letra Verdana, negrita de 30 pixeles y finalmente en la posición (x,y) igual a (10,30) donde dibujamos la puntuación.

En el método gameOver() modificamos el segundo parámetro para mostrar la puntuación alcanzada:

		JOptionPane.showMessageDialog(this, "your score is: " + getScore(),
				"Game Over", JOptionPane.YES_NO_OPTION);

En la clase Ball el método move() ha sido modificado para considerar la nueva propiedad de velocidad "game.speed". Cuando la pelota cambiaba de dirección las propiedades de velocidad xa y ya eran modificadas a 1 o -1. Ahora considerando la velocidad estas propiedades son cambiadas a game.speed o -game.speed. También se ha agregado en el condicional if(collision()) que la velocidad se incremente "game.speed++".

package com.edu4java.minitennis8;

import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Ball {
	private static final int DIAMETER = 30;
	
	int x = 0;
	int y = 0;
	int xa = 1;
	int ya = 1;
	private Game game;

	public Ball(Game game) {
		this.game = game;
	}

	void move() {
		boolean changeDirection = true;
		if (x + xa < 0)
			xa = game.speed;
		else if (x + xa > game.getWidth() - DIAMETER)
			xa = -game.speed;
		else if (y + ya < 0)
			ya = game.speed;
		else if (y + ya > game.getHeight() - DIAMETER)
			game.gameOver();
		else if (collision()){
			ya = -game.speed;
			y = game.racquet.getTopY() - DIAMETER;
			game.speed++;
		} else 
			changeDirection = false;
		
		if (changeDirection) 
			Sound.BALL.play();
		x = x + xa;
		y = y + ya;
	}

	private boolean collision() {
		return game.racquet.getBounds().intersects(getBounds());
	}

	public void paint(Graphics2D g) {
		g.fillOval(x, y, DIAMETER, DIAMETER);
	}

	public Rectangle getBounds() {
		return new Rectangle(x, y, DIAMETER, DIAMETER);
	}
}

A continuación vemos la clase Racquet:

package com.edu4java.minitennis8;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

public class Racquet {
	private static final int Y = 330;
	private static final int WITH = 60;
	private static final int HEIGHT = 10;
	int x = 0;
	int xa = 0;
	private Game game;

	public Racquet(Game game) {
		this.game = game;
	}

	public void move() {
		if (x + xa > 0 && x + xa < game.getWidth() - WITH)
			x = x + xa;
	}

	public void paint(Graphics2D g) {
		g.fillRect(x, Y, WITH, HEIGHT);
	}

	public void keyReleased(KeyEvent e) {
		xa = 0;
	}

	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_LEFT)
			xa = -game.speed;
		if (e.getKeyCode() == KeyEvent.VK_RIGHT)
			xa = game.speed;
	}

	public Rectangle getBounds() {
		return new Rectangle(x, Y, WITH, HEIGHT);
	}

	public int getTopY() {
		return Y - HEIGHT;
	}
}

Aquí la modificación es similar que en Ball. En el método keyPressed(KeyEvent e) la modificación de la velocidad xa pasa de -1 y 1 a -game.speed y game.speed.

Nota: según el estándar de "Java Beans" el acceso a la propiedad "game.speed" debería hacerse usando un método de la forma "game.getSpeed()". El accesos directo a una propiedad es considerado casi un pecado mortal en el ámbito de java empresarial. Curiosamente en el entorno de desarrollo de juegos es muy común y esta justificado por eficiencia. Esto es especialmente importante en programación para móviles donde los recursos suelen ser más escasos.

 

<< Anterior Siguiente >>