Agregando el sprite raqueta

En este tutorial agregaremos la raqueta mediante un Sprite llamado Racquet. La raqueta se moverá hacia la izquierda o derecha cuando oprimamos las teclas del cursor por lo que nuestro programa necesita leer del teclado.

Nuevo Sprite Racquet

Lo primero que hacemos es agregar en la clase Game una nueva propiedad llamada racquet donde mantendremos el Sprite que maneja la raqueta. En el método move() añadimos una llamada a racquet.move() y en paint() una llamada a racquet.paint(). Hasta ahora todo es similar al sprite Ball pero como la posición de la raqueta responde al teclado tenemos que hacer algo más.

package com.edu4java.minitennis5;

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.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);
	}
	
	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 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 el constructor de la clase game se puede ver como se registra un listener para capturar los eventos del teclado. En el método keyPressed() del listener informamos a la raqueta que una tecla ha sido oprimida llamando a racquet.keyPressed(e). Lo mismo hacemos para keyReleased(). Con esto el Sprite racquet se enterará cuando una tecla sea oprimida. Veamos ahora las clases Ball y Racquet que implementan los sprites.

package com.edu4java.minitennis5;

import java.awt.Graphics2D;

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

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

	void move() {
		if (x + xa < 0)
			xa = 1;
		if (x + xa > game.getWidth() - 30)
			xa = -1;
		if (y + ya < 0)
			ya = 1;
		if (y + ya > game.getHeight() - 30)
			ya = -1;

		x = x + xa;
		y = y + ya;
	}

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

La clase Ball no tiene cambios. Comparémosla con la clase Racquet:

package com.edu4java.minitennis5;

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

public class Racquet {
	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()-60)
			x = x + xa;
	}

	public void paint(Graphics2D g) {
		g.fillRect(x, 330, 60, 10);
	}

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

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

A diferencia de Ball, Racquet no tiene propiedades para la posición "y" ni la velocidad "ya". Esto es debido a que la raqueta no variará su posición vertical, solo se moverá hacia la izquierda o derecha, nunca hacia arriba o abajo. En el método paint la instrucción g.fillRect(x, 330, 60, 10) define un rectángulo de 60 por 10 pixeles en la posición (x,y)=(x,330). Como vemos "x" puede variar pero "y" está fijada a 330 pixeles del limite superior del lienzo.

El método move() es similar al de Ball en el sentido de incrementar en "xa" la posición "x" y controlar que el sprite no se salga de los limites.

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

Inicialmente el valor de "x" es cero lo que indica que la raqueta estará en el limite izquierdo del lienzo. "xa" también está inicializado a cero, lo que hace que en principio la raqueta aparezca estática ya que x = x + xa no modificará "x" mientras "xa" sea cero.

Cuando alguien presione una tecla el método keyPressed de Racquet será llamado y este pondrá "xa" en 1 si la tecla presionada es la de dirección derecha (KeyEvent.VK_RIGHT) lo que a su vez hará que la raqueta se mueva a la derecha la próxima vez que se llame al método move (recordar x = x + xa). De la misma forma si se presiona la tecla KeyEvent.VK_LEFT se moverá a la izquierda.

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

Cuando una tecla deja de ser presionada el método keyReleased es llamado y "xa" pasa a valer cero lo que hace que el movimiento de la raqueta se detenga.

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

Si ejecutamos el ejemplo podemos ver como la pelota se mueve rebotando contra los límites y la raqueta se mueve cuando presionamos las teclas de dirección correspondientes. Pero cuando la pelota choca con la raqueta la atraviesa pareciendo como si esta no existiese. En el próximo tutorial veremos como hacer que la pelota rebote sobre la raqueta.

 

<< Anterior Siguiente >>