Moving Sprites
Moving Sprites
Moving sprites
In this part of the Java 2D games tutorial we will work with sprites.
The term sprite has several meanings. It is used to denote an image or an animation in a
scene. It is also used to represent any movable object in a game. Also one of the
meanings is the code that encapsulates a character in a game. In our tutorial by using
sprite we refer to a movable object or its Java class.
Moving sprite
In the first example we have a spacecraft. We can move the spacecraft on the board
using the cursor keys.
Craft.java
package com.zetcode;
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Craft {
private
private
private
private
private
int dx;
int dy;
int x;
int y;
Image image;
public Craft() {
}
initCraft();
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
This class represents a spacecraft. In this class we keep the image of the sprite and the
coordinates of the sprite. The keyPressed() and keyReleased() methods control
whether the sprite is moving.
public void move() {
x += dx;
y += dy;
}
The move() method changes the coordinates of the sprite. These x and y values are used
in thepaintComponent() method to draw the image of the sprite.
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
When we release the left cursor key, we set the dx variable to zero. The spacecraft will
stop moving.
Board.java
package com.zetcode;
import
import
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Toolkit;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyAdapter;
java.awt.event.KeyEvent;
javax.swing.JPanel;
javax.swing.Timer;
initBoard();
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
Toolkit.getDefaultToolkit().sync();
@Override
public void keyPressed(KeyEvent e) {
craft.keyPressed(e);
}
In the doDrawing() method, we draw the spacecraft with the drawImage() method. We
get the image and the coordinates from the sprite class.
@Override
public void actionPerformed(ActionEvent e) {
craft.move();
repaint();
}
The actionPerformed() method is called every DELAY ms. We move the sprite and
repaint the board.
private class TAdapter extends KeyAdapter {
@Override
public void keyReleased(KeyEvent e) {
craft.keyReleased(e);
}
@Override
public void keyPressed(KeyEvent e) {
craft.keyPressed(e);
}
}
In the Board class we listen for key events. The overridden methods of
the KeyAdapter class delegate the processing to the methods of the Craft class.
MovingSpriteEx.java
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class MovingSpriteEx extends JFrame {
public MovingSpriteEx() {
}
initUI();
Shooting missiles
In the next example we will add another sprite type to our examplea missile. The
missiles are launched with the Space key.
Sprite.java
package com.zetcode;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Sprite {
protected
protected
protected
protected
protected
protected
int x;
int y;
int width;
int height;
boolean vis;
Image image;
width = image.getWidth(null);
height = image.getHeight(null);
The Sprite class shares common code from the Missile and Craft classes.
public Sprite(int x, int y) {
this.x = x;
this.y = y;
vis = true;
The constructor initiates the x and y coordiates and the vis variable.
Missile.java
package com.zetcode;
public class Missile extends Sprite {
private final int BOARD_WIDTH = 390;
private final int MISSILE_SPEED = 2;
public Missile(int x, int y) {
super(x, y);
}
initMissile();
loadImage("missile.png");
getImageDimensions();
if (x > BOARD_WIDTH) {
vis = false;
}
if (x > BOARD_WIDTH) {
vis = false;
}
The missile moves at constant speed. When it hits the right border of the Board, it
becomes invisible. It is then removed from the list of missiles.
Craft.java
package com.zetcode;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
public class Craft extends Sprite {
private int dx;
private int dy;
private ArrayList missiles;
public Craft(int x, int y) {
super(x, y);
}
initCraft();
}
if (key == KeyEvent.VK_LEFT) {
dx = -1;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 1;
}
if (key == KeyEvent.VK_UP) {
dy = -1;
}
if (key == KeyEvent.VK_DOWN) {
dy = 1;
}
}
public void fire() {
missiles.add(new Missile(x + width, y + height / 2));
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
The fire() method creates a new Missile object and adds it to the missiles ArrayList.
public ArrayList getMissiles() {
return missiles;
}
java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Toolkit;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.KeyAdapter;
java.awt.event.KeyEvent;
java.util.ArrayList;
javax.swing.JPanel;
javax.swing.Timer;
final
final
final
Timer
Craft
public Board() {
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.BLACK);
setDoubleBuffered(true);
craft = new Craft(ICRAFT_X, ICRAFT_Y);
timer = new Timer(DELAY, this);
timer.start();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
Toolkit.getDefaultToolkit().sync();
repaint();
ms.remove(i);
craft.move();
In the doDrawing() method, we draw the craft and all the available missiles.
private void updateMissiles() {
ArrayList ms = craft.getMissiles();
for (int i = 0; i < ms.size(); i++) {
Missile m = (Missile) ms.get(i);
if (m.isVisible()) {
m.move();
} else {
}
}
ms.remove(i);
In the updateMissiles() method we parse all missiles from the missiles list. Depending
on what theisVisible() method returns, we either move the missile or remove it from
the container.
ShootingMissilesEx.java
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class ShootingMissilesEx extends JFrame {
public ShootingMissilesEx() {
}
initUI();
setTitle("Shooting missiles");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
});