Sprites - Velocidad y dirección

Cada objeto que se mueve en la pantalla tiene características propias como la posición (x,y), la velocidad y la dirección en que se mueve, etc. Todas estas características se pueden aislar en un objeto que llamaremos Sprite.

Velocidad y dirección

En el tutorial anterior logramos que la pelota (el círculo) se moviera hacia abajo y a la derecha a un píxel por vuelta en el Game Loop. Cuando llegaba al limite de la pantalla la pelota seguía su curso desapareciendo del lienzo. Lo que haremos a continuación es que la pelota rebote en los limites del lienzo cambiando su dirección.

package com.edu4java.minitennis3;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;

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

	int x = 0;
	int y = 0;
	int xa = 1;
	int ya = 1;

	private void moveBall() {
		if (x + xa < 0)
			xa = 1;
		if (x + xa > getWidth() - 30)
			xa = -1;
		if (y + ya < 0)
			ya = 1;
		if (y + ya > getHeight() - 30)
			ya = -1;
		
		x = x + xa;
		y = y + ya;
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g.fillOval(x, y, 30, 30);

	}

	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.moveBall();
			game.repaint();
			Thread.sleep(10);
		}
	}
}

En el código anterior se agregaron dos propiedades "xa" y "ya" que representan la velocidad en que se mueve la pelota. Si xa=1, la pelota se mueve hacia la derecha a un píxel por vuelta del Game Loop y si xa=-1, la pelota se mueve hacia la izquierda. Similarmente ya=1 mueve hacia abajo y ya=-1 mueve hacia arriba. Esto lo logramos con las líneas "x = x + xa" e "y = y + ya" del método moveBall().

Antes de ejecutar las instrucciones anteriores verificamos que la pelota no salga de los márgenes del lienzo. Por ejemplo cuando la pelota alcance el margen derecho o lo que es lo mismo cuando (x + xa > getWidth() - 30) lo que haremos es cambiar la dirección del movimiento sobre el eje x o lo que es lo mismo asignar menos uno a xa "xa = -1".

	private void moveBall() {
		if (x + xa < 0)
			xa = 1;
		if (x + xa > getWidth() - 30)
			xa = -1;
		if (y + ya < 0)
			ya = 1;
		if (y + ya > getHeight() - 30)
			ya = -1;
		
		x = x + xa;
		y = y + ya;
       
	}
    

Cada sentencia if limita un borde del lienzo.

Crear el Sprite Ball (pelota en inglés)

La idea es crear una clase llamada Ball que aisle todo lo referente a la pelota. En el siguiente código podemos ver como extraemos todo el código referente a la pelota de la clase Game2 y lo incorporamos a nuestra nueva clase Ball.

package com.edu4java.minitennis3;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;

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

	Ball ball = new Ball(this);

	private void move() {
		ball.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);
	}

	public static void main(String[] args) throws InterruptedException {
		JFrame frame = new JFrame("Mini Tennis");
		Game2 game = new Game2();
		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);
		}
	}
}

        

El Sprite Ball necesita que le envíen una referencia al objeto Game para obtener los limites del lienzo y así saber cuando debe cambiar de dirección. En el método move() de la clase Ball se llama a game.getWidth() y game.getHeight().

package com.edu4java.minitennis3;

import java.awt.Graphics2D;

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

	public Ball(Game2 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);
	}
}

Si ejecutamos Game2 obtendremos el mismo resultado que si ejecutamos la versión anterior Game. La conveniencia de esta separación del código referente a la pelota en una clase de tipo Sprite se vuelve más obvia cuando incluimos la raqueta mediante un nuevo Sprite en un próximo tutorial.

 

<< Anterior Siguiente>>