Sprites - Speed and direction

All the objects moving in the screen have their own characteristics such as the position (x,y), speed and direction, etc. All of these characteristics can be isolated in an object which we are going to call "Sprite".

Speed and direction

In the last tutorial we got the ball (circle) to move. It moved downwards and to the right, one pixel every round of the Game Loop. When it got to the border of the screen the ball continued, vanishing from the canvas. Now, we are going to make the ball bounce back once it touches de borders of the canvas, changing its direction.

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

In this code we can see that there are two more properties; "xa" and "ya", which represents the speed in which the ball is moving. If xa=1, the ball moves to the right, one pixel every round of the Game Loop, if xa=-1, the ball moves to the left. In the same way ya=1 moves the ball down and ya=-1 moves the ball up. This is done with the lines, "x = x + xa" and "y = y + ya" of the moveBall() method.

Before running the previous instructions, we verify that the ball doesn´t go out of the borders of the canvas. For example, when the ball gets to the right border, or when (x + xa > getWidth() - 30), what we`ll do, is to change the direction of the movement on the "x" axis or what is the same we assign -1 to "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;
	}

Each if sentence limits a border of the canvas.

Creation of the "Ball" Sprite

The idea is to create a class called Ball which isolates everything that has to do with the ball. In the following code we can see how we extract all the code from the class Game2, which has to do with the ball, and we add it to our new class 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);
		}
	}
}

        

The Ball sprite needs the reference to the Game object to obtain the borders of the canvas and in this way know when to change the direction. In the move() method the Ball class calls the methods game.getWidth() and 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);
	}
}

If we execute Game2, we will obtain the same result as if we execute the last Game version. The convenience of putting the code of the Ball into a Sprite type class becomes more clear when we include the racquet with a new Sprite, in the next tutorial.

 

<< Game loop and Animation Events. Keyboard input >>