In this tutorial, we'll look at how to create a simple game in Java:
- Moving a sprite around the screen
- Controlling the sprite using the keyboard
- Loading a PNG image as the sprite graphic
- Ensuring the sprite stays within the boundaries of the playfield.
Step 1: Setting Up Your Java Project
Before we begin coding, make sure you have the following:
- A Java Development Kit (JDK) installed (JDK 8 or later is recommended)
- A text editor (VS Code, IntelliJ, or Eclipse)
- A PNG image file for your sprite (name it
sprite.png
and place it in your project folder)
piskelapp.com is an amazing free, online pixel graphics editor.
Step 2: Creating a Basic Java Window
Every game needs a playfield of some kind so we need to generate a window to display our game content. We'll use Java Swing to create a window with a drawing area.
Create a new Java file called ControlledSprite.java
and paste the following code:
import javax.swing.*;
import java.awt.*;
public class ControlledSprite extends JPanel {
public ControlledSprite() {
setFocusable(true); // Allows the panel to receive keyboard input
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(200, 100, 50, 50); // Draws a simple red circle as a placeholder sprite
}
public static void main(String[] args) {
JFrame frame = new JFrame("Simple Game");
ControlledSprite panel = new ControlledSprite();
frame.add(panel);
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
This code creates a window and draws a red circle, which will act as our sprite for now.
Step 3: Moving the Sprite with the Keyboard
Now, let's make the sprite move using the keyboard. Modify your ControlledSprite
class to implement KeyListener
:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class ControlledSprite extends JPanel implements KeyListener {
private int x = 200, y = 100; // Sprite position
private final int SPEED = 5; // Movement speed
public ControlledSprite() {
setFocusable(true);
addKeyListener(this);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(x, y, 50, 50);
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) x -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) x += SPEED;
if (e.getKeyCode() == KeyEvent.VK_UP) y -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_DOWN) y += SPEED;
repaint(); // Redraw sprite at new position
}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
public static void main(String[] args) {
JFrame frame = new JFrame("Controlled Sprite");
ControlledSprite panel = new ControlledSprite();
frame.add(panel);
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Now, when you press the arrow keys, the sprite moves around the screen.
Step 4: Loading a PNG Image as the Sprite
Let's replace the red circle with an actual sprite image. Make sure you have a sprite.png
file in the same directory as your Java file.
Modify the code to load and display the sprite image:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ControlledSprite extends JPanel implements KeyListener {
private BufferedImage sprite;
private int x = 200, y = 100; // Sprite position
private final int SPEED = 5; // Movement speed
public ControlledSprite() {
try {
sprite = ImageIO.read(new File("sprite.png")); // Load sprite image
} catch (Exception e) {
System.err.println("Image not found!");
}
setFocusable(true);
addKeyListener(this);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (sprite != null) {
g.drawImage(sprite, x, y, null);
}
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) x -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) x += SPEED;
if (e.getKeyCode() == KeyEvent.VK_UP) y -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_DOWN) y += SPEED;
repaint();
}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
public static void main(String[] args) {
JFrame frame = new JFrame("Controlled Sprite");
ControlledSprite panel = new ControlledSprite();
frame.add(panel);
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Now, the sprite is an image instead of a red circle!
Step 5: Keeping the Sprite Inside the Playfield
Modify the movement code to prevent the sprite from leaving the screen:
@Override
public void keyPressed(KeyEvent e) {
if (sprite != null) {
int spriteWidth = sprite.getWidth();
int spriteHeight = sprite.getHeight();
int panelWidth = getWidth();
int panelHeight = getHeight();
if (e.getKeyCode() == KeyEvent.VK_LEFT && x > 0) x -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_RIGHT && x < panelWidth - spriteWidth) x += SPEED;
if (e.getKeyCode() == KeyEvent.VK_UP && y > 0) y -= SPEED;
if (e.getKeyCode() == KeyEvent.VK_DOWN && y < panelHeight - spriteHeight) y += SPEED;
}
repaint();
}
Full, Commented Code
// This example introduces a graphical sprite under keyboard control
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ControlledSprite extends JPanel implements KeyListener {
private BufferedImage sprite; // Stores the sprite image
private int x = 250-16, y = 150-32; // Initial sprite position
private final int SPEED = 200; // Movement speed (pixels per second)
private boolean up, down, left, right; // Movement flags
private long lastTime; // Stores the last frame's timestamp
public ControlledSprite() {
// Attempt to load the sprite image
try {
sprite = ImageIO.read(new File("sprite.png"));
} catch (Exception e) {
System.err.println("Error: Image file not found!");
}
setFocusable(true); // Ensures the panel can receive keyboard input
addKeyListener(this); // Adds key listener for movement
lastTime = System.nanoTime(); // Initialize time tracking
// Timer to update movement every ~16ms (~60 FPS)
Timer timer = new Timer(16, e -> updatePosition());
timer.start();
}
private void updatePosition() {
long now = System.nanoTime();
double deltaTime = (now - lastTime) / 1_000_000_000.0; // Convert nanoseconds to seconds
lastTime = now;
// Ensure sprite is loaded before checking its size
if (sprite != null) {
int spriteWidth = sprite.getWidth();
int spriteHeight = sprite.getHeight();
int panelWidth = getWidth();
int panelHeight = getHeight();
// Move sprite, ensuring it stays within bounds
if (left) x = Math.max(0, x - (int) (SPEED * deltaTime));
if (right) x = Math.min(panelWidth - spriteWidth, x + (int) (SPEED * deltaTime));
if (up) y = Math.max(0, y - (int) (SPEED * deltaTime));
if (down) y = Math.min(panelHeight - spriteHeight, y + (int) (SPEED * deltaTime));
}
repaint(); // Request repaint to update sprite position
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // Clears the previous frame
if (sprite != null) {
g.drawImage(sprite, x, y, null); // Draw the sprite at its new position
}
}
// Handles key press events
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT -> left = true;
case KeyEvent.VK_RIGHT -> right = true;
case KeyEvent.VK_UP -> up = true;
case KeyEvent.VK_DOWN -> down = true;
}
}
// Handles key release events
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT -> left = false;
case KeyEvent.VK_RIGHT -> right = false;
case KeyEvent.VK_UP -> up = false;
case KeyEvent.VK_DOWN -> down = false;
}
}
@Override
public void keyTyped(KeyEvent e) {} // Not used, but required by KeyListener
public static void main(String[] args) {
// Create a frame to contain the panel
JFrame frame = new JFrame("Controlled Sprite");
ControlledSprite panel = new ControlledSprite();
frame.add(panel);
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Next Steps
Hopefully you can now understand how to create a basic game with a controllable sprite. If there is interest, in future tutorials we can add animation, collision detection, and more!
Posted Using INLEO
Thanks for your contribution to the STEMsocial community. Feel free to join us on discord to get to know the rest of us!
Please consider delegating to the @stemsocial account (85% of the curation rewards are returned).
You may also include @stemsocial as a beneficiary of the rewards of this post to get a stronger support.