
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.pngand 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