Creando una clase Sound para nuestro juego

Para guardar los audioclips de nuestro juego creamos una clase Sound que tendrá una constante con un audioclip por cada sonido que usemos. Estas constantes son públicas para que cualquier objeto que tenga acceso a ellas pueda reproducirlas. Por ejemplo en la clase Ball podemos reproducir el sonido del rebote de la pelota usando Sound.BALL.play() en el momento que detectamos que la pelota cambia de dirección.

package com.edu4java.minitennis7;

import java.applet.Applet;
import java.applet.AudioClip;

public class Sound {
	public static final AudioClip BALL = Applet.newAudioClip(Sound.class.getResource("ball.wav"));
	public static final AudioClip GAMEOVER = Applet.newAudioClip(Sound.class.getResource("gameover.wav"));
	public static final AudioClip BACK = Applet.newAudioClip(Sound.class.getResource("back.wav"));
}

Los objetos audioclips se crearán al cargarse la clase Sound la primera vez que alguien use la clase Sound. A partir de este momento serán reutilizados una y otra vez. Ahora veamos las modificaciones en la clase Game:

package com.edu4java.minitennis7;

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);

	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);
	}
	
	public void gameOver() {
		Sound.BACK.stop();
		Sound.GAMEOVER.play();
		JOptionPane.showMessageDialog(this, "Game Over", "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);
		}
	}
}

En la última línea del constructor de la clase Game añadimos Sound.BACK.loop(), lo que iniciará la reproducción de nuestra música de fondo que se repetirá hasta que se alcance el método gameOver(), donde detenemos la música de fondo con Sound.BACK.stop(). A continuación de Sound.BACK.stop() y antes del popup informamos que se termino la partida reproduciendo "Game Over" Sound.GAMEOVER.play().

En la clase Ball modificamos el método move() para que se reproduzca Sound.BALL cuando la pelota rebote.

package com.edu4java.minitennis7;

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 = 1;
		else if (x + xa > game.getWidth() - DIAMETER)
			xa = -1;
		else if (y + ya < 0)
			ya = 1;
		else if (y + ya > game.getHeight() - DIAMETER)
			game.gameOver();
		else if (collision()){
			ya = -1;
			y = game.racquet.getTopY() - DIAMETER;
		} 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);
	}
}

Lo que hice en move() es agregar una variable changeDirection que inicializo a true. Añadiendo un else a cada if y colocando un changeDirection = false que sólo se ejecutará si ninguna condición en los if es cumplida, conseguimos enterarnos si la bola ha rebotado. Si la pelota ha rebotado changeDirection será verdadero y Sound.BALL.play() será ejecutado.

<< Anterior Siguiente >>