Creating Your First Game in Java

in #technology4 days ago

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

Sort:  

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.