Java Game
Notebook to display basic setup for a game using AWT and Swing.
This blog shows up how to set up a basic game in Java!
Tools
Here we only use the built in Java libraries AWT and Swing.
Overview
We create 4 classes. One class contains the game loop, and manages the game. A game loop essentially runs every couple of miliseconds to update the game state. Another class contains the player controller, which is how you can move around and jump. One class draws the ground, and the other class is for the obstacle.
Setup
Create a new directory for all of the java files, so that they can be part of the same package. The reason that this isn't done in a Notebook is because the classes depend on each other, so individual cells containing classes won't be able to run.
Playing/Testing
Run the Game.java file.
// My package is called JavaCode
package JavaCode;
// Necessary imports
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
// Inheriting from JPanel using extends JPanel
// This way we can override the paint method. This is important so that the screen is cleared before it is repainted. Otherwise, we can't see movement!
public class Game extends JPanel {
// Instantiating the player (ball)
Controller controller = new Controller(this);
// Instantiating the ground
Ground ground = new Ground(this);
public Game() {
// Adding key listener to constructor.
// This allows for user input.
addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
controller.keyReleased(e);
}
@Override
public void keyPressed(KeyEvent e) {
controller.keyPressed(e);
}
});
setFocusable(true);
}
// Game loop, simply calling the method for the player to move.
private void move() {
controller.move();
}
// Overriding the paint method.
// Super.paint is needed since we repaint every 10 miliseconds.
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Painting the ground and the player.
controller.paint(g2d);
ground.paint(g2d);
}
// Simple Game Over screen
public void gameOver() {
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
// Creating the JFrame
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("ADfastpages Game");
// New Game Object
Game game = new Game();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// The game loop. Causes the progression of things in the game.
while (true) {
game.move();
game.repaint();
// Things aren't updated every frame. They are updated every 10 ms.
Thread.sleep(10);
}
}
}
package JavaCode;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.Rectangle;
public class Controller {
// x and y are used to locate the player in 2D space
int x = 0;
int y = 300;
// vx and vy are used to move the player around in certain increments.
int vx = 0;
int vy = 1;
// The dimensions of the player. These remain constant.
// We need this for a hitbox.
private static final int WIDTH = 30;
private static final int HEIGHT = 30;
private Game game;
// Creating an obstacle object here.
// We do it in this class since obstacles should spawn relative to the player.
Obstacle obstacle = new Obstacle(game);
public Controller(Game game) {
// This object is instantiated in the game class, so that the controller can contain a reference to the game state.
this.game= game;
}
// Method to move the player
public void move() {
// Making sure we move within the boundaries.
if (x + vx > 0 && x + vx < game.getWidth()-60)
x = x + vx;
if (y + vy > 0 && x + vy < game.getHeight()-60)
y = y + vy;
// Detecting collision so that the game can end.
// References the Game Over method contained in the game class.
if (collisionObstacle()) {
game.gameOver();
}
// Implementing realistic ground.
if (y < game.getHeight() / 2) {
if (collisionGround()) {
vy = -1;
}
}
else {
// Stopping player if it hits the ground.
if (collisionGround()) {
vy = 0;
}
else {
vy = 1;
}
}
}
// The paint method needs to paint both the player, as well as call the obstacle paint method to paint the obstacle.
public void paint(Graphics2D g) {
g.fillOval(x, y, WIDTH, HEIGHT);
obstacle.paint(g, 100);
}
// Creating a hitbox for the player.
public Rectangle getBounds() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}
// Making sure the player doesn't move without key being pressed.
public void keyReleased(KeyEvent e) {
vx = 0;
}
// Input movement
public void keyPressed(KeyEvent e) {
// A and D move the player side to side.
if (e.getKeyCode() == KeyEvent.VK_A)
vx = -2;
if (e.getKeyCode() == KeyEvent.VK_D)
vx = 2;
// Jump functionality.
if (vy == 0) {
if (e.getKeyCode() == KeyEvent.VK_SPACE)
do {
y = y - 1;
}
while (y > 250);
vy = -1;
}
}
// Method to detect collision with the ground.
private boolean collisionGround() {
return game.ground.getBounds().intersects(getBounds());
}
// Separate method to detect collision with an obstacle.
// Needed since collision with different things should cause different results.
private boolean collisionObstacle() {
return this.obstacle.getBounds().intersects(getBounds());
}
}
package JavaCode;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Obstacle {
// Rererence to the game object.
private Game game;
// Dimensions for obstacle hitbox.
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
// Updating x position to spawn at.
private int localx = 60;
public Obstacle(Game game) {
this.game= game;
}
// Paint method used to displat the ground.
// Needs an input for the x position as well, since the obstacle shouldn't always spawn in the same place.
public void paint(Graphics2D g, int x) {
localx = x;
g.fillRect(localx, 325, WIDTH, HEIGHT);
}
// Setting up a collider to detect collision.
public Rectangle getBounds() {
return new Rectangle(localx, 325, WIDTH, HEIGHT);
}
}
package JavaCode;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ground {
// Rererence to the game object.
private Game game;
private static final int HEIGHT = 30;
public Ground(Game game) {
this.game= game;
}
// Paint method used to displat the ground.
public void paint(Graphics2D g) {
g.fillRect(0, game.getHeight() - 30, game.getWidth(), 30);
}
// Setting up a collider to detect collision.
public Rectangle getBounds() {
return new Rectangle(0, game.getHeight() - 30, game.getWidth(), HEIGHT);
}
}