Ball dodging game
Build a simple Java game, which is a dodging game. The changes required are:
- set up a difficulty selecting screen, easy, normal, and hard, instead of difficulty level increases automatically. (higher level means more enemies and faster enemy speed)
- player movement control by WASD or mouse (choose the easiest way)
- player does not need to collect anything, just try to survive as long as they could
- set up a health bar for 120 points, it will lose 30 points every time you collide with enemies.
Solution
BallSpawnFrame.java
public class BallSpawnFrame {
Coordinates startCoordinates;
Coordinates endCoordinates;
public BallSpawnFrame(Coordinates startCoordinates, Coordinates endCoordinates) {
this.startCoordinates = startCoordinates;
this.endCoordinates = endCoordinates;
}
public double getXBeginning() {
return startCoordinates.getxPos();
}
public double getXEnding() {
return endCoordinates.getxPos();
}
public double getYEnding() {
return endCoordinates.getyPos();
}
public double getYBeginning() {
return startCoordinates.getyPos();
}
}
BlueBall.java
import java.awt.*;
public class BlueBall {
Coordinates coordinates;
final MovingVector movingVector;
private final Color bodyColor;
private final int ballDiameter;
public BlueBall(Coordinates coordinates, MovingVector movingVector, int ballDiameter) {
this.coordinates = coordinates;
this.movingVector = movingVector;
this.ballDiameter = ballDiameter;
bodyColor = Color.BLUE;
}
public void draw(Graphics g) {
g.setColor(bodyColor);
g.drawOval((int)(coordinates.getxPos()- ballDiameter/2), (int)(coordinates.getyPos() – ballDiameter/2), ballDiameter, ballDiameter);
g.fillOval((int)(coordinates.getxPos() – ballDiameter/2), (int)(coordinates.getyPos() – ballDiameter/2), ballDiameter, ballDiameter);
}
public void moveByVector() {
double xPos = coordinates.getxPos() + movingVector.getX();
double yPos = coordinates.getyPos() + movingVector.getY();
coordinates = new Coordinates(xPos, yPos);
}
public Coordinates getCoordinates() {
return coordinates;
}
}
BoardController.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.concurrent.TimeUnit;
public class BoardController {
private JFrame parent;
MainGamePanel mainGamePanel;
final BallSpawnFrame ballSpawnFrame;
BlueBall[] blueBalls;
final int ballSize;
private Timer playingTimer;
private Player player;
private final Difficulty difficulty;
private boolean gameStarted = false;
private int gamePanelWidth;
private int gamePanelHeight;
public BoardController(JFrame parent, MainGamePanel mainGamePanel, Difficulty difficulty, int windowWidth, int windowHeight, int ballSize) {
this.parent = parent;
this.mainGamePanel = mainGamePanel;
this.difficulty = difficulty;
this.ballSize = ballSize;
this.gamePanelWidth = windowWidth;
this.gamePanelHeight = windowHeight;
ballSpawnFrame = new BallSpawnFrame(new Coordinates(-50, -50), new Coordinates(windowWidth + 50, windowHeight + 50));
blueBalls = new BlueBall[difficulty.getNumberOfObstacles()];
player = new Player(new Coordinates(windowWidth/2, windowHeight/2));
loadEnvironment();
}
private void startGame() {
gameStarted = true;
playingTimer = new Timer(40, timerAction);
playingTimer.start(); mainGamePanel.getInformationBar().setGameStartedTimeStamp(System.currentTimeMillis());
}
private ActionListener timerAction = (e) -> {
Point mousePoint = mainGamePanel.getMousePosition();
if(mousePoint != null) movePlayer(mousePoint);
moveBalls();
mainGamePanel.refreshView();
};
private void movePlayer(Point mousePoint) {
if(mousePoint.x > player.getCoordinates().getxPos() – 5 && mousePoint.x < player.getCoordinates().getxPos() + 5
&& mousePoint.y > player.getCoordinates().getyPos() – 5 && mousePoint.y < player.getCoordinates().getyPos() + 5) return;
float angle = (float) Math.toDegrees(Math.atan2(mousePoint.y – player.getCoordinates().getyPos(),
mousePoint.x – player.getCoordinates().getxPos()));
if(angle < 0){
angle += 360;
}
double x = (difficulty.getObstaclesMovingSpeed() * Math.cos(Math.toRadians(angle)));
double y = (difficulty.getObstaclesMovingSpeed() * Math.sin(Math.toRadians(angle)));
player.moveByVector(new MovingVector(x, y));
}
private void moveBalls() {
for(int i = 0; i< blueBalls.length; i++) {
Coordinates ballCoordinates = blueBalls[i].getCoordinates();
if(ballCoordinates.getxPos() < ballSpawnFrame.getXBeginning()
|| ballCoordinates.getxPos() > ballSpawnFrame.getXEnding()
|| ballCoordinates.getyPos() > ballSpawnFrame.getYEnding()
|| ballCoordinates.getyPos() < ballSpawnFrame.getYBeginning() ) {
Coordinates newBallCoordinates = randomizeCoordinates();
MovingVector movingVector = randomizeMovingVector();
BlueBall blueBall = new BlueBall(newBallCoordinates, movingVector, ballSize);
blueBalls[i] = blueBall;
}
if(checkForCollision(blueBalls[i])) {
int currentHealthPoints = mainGamePanel.getInformationBar().getCurrentHealthPoints();
mainGamePanel.getInformationBar().setCurrentHealthPoints(currentHealthPoints – 30);
if(mainGamePanel.getInformationBar().getCurrentHealthPoints() == 0) {
long timeStamp = System.currentTimeMillis();
String input = JOptionPane.showInputDialog(parent, “To continue the game please write correct answer: \n 1 + 1 is equal to…”);
long gameStartedTimeStamp = mainGamePanel.getInformationBar().getGameStartedTimeStamp();
try {
if(input != null && Integer.parseInt(input) == 2) {
mainGamePanel.getInformationBar().setCurrentHealthPoints(120);
mainGamePanel.getInformationBar().setGameStartedTimeStamp(gameStartedTimeStamp + (System.currentTimeMillis() – timeStamp));
}
else {
JOptionPane.showMessageDialog(parent,
String.format(“Playing time: %02d : %02d”,
TimeUnit.MILLISECONDS.toMinutes(timeStamp – gameStartedTimeStamp),
TimeUnit.MILLISECONDS.toSeconds(timeStamp – gameStartedTimeStamp) –
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeStamp – gameStartedTimeStamp))),
“Game over”,
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(parent,
“Wrong answer.”,
“Game over”,
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
Coordinates newBallCoordinates = randomizeCoordinates();
MovingVector movingVector = randomizeMovingVector();
BlueBall blueBall = new BlueBall(newBallCoordinates, movingVector, ballSize);
blueBalls[i] = blueBall;
}
blueBalls[i].moveByVector();
}
}
private boolean checkForCollision(BlueBall blueBall) {
double ballXCoordinates = blueBall.getCoordinates().getxPos();
double ballYCoordinates = blueBall.getCoordinates().getyPos();
if(player.getCoordinates().getxPos() – ballSize/2 < ballXCoordinates + ballSize/2
&& ballXCoordinates – ballSize/2 < player.getCoordinates().getxPos() + ballSize/2
&& player.getCoordinates().getyPos() – ballSize/2 < ballYCoordinates + ballSize/2
&& player.getCoordinates().getyPos() + ballSize/2 > ballYCoordinates – ballSize/2) {
return true;
}
return false;
}
private void loadEnvironment() {
for(int i = 0; i< blueBalls.length; i++){
Coordinates ballCoordinates = randomizeCoordinates();
MovingVector movingVector = randomizeMovingVector();
BlueBall blueBall = new BlueBall(ballCoordinates, movingVector, ballSize);
blueBalls[i] = blueBall;
}
}
private MovingVector randomizeMovingVector() {
double angle = Math.random() * 360;
double x = (difficulty.getObstaclesMovingSpeed() * Math.cos(Math.toRadians(angle)));
double y = (difficulty.getObstaclesMovingSpeed() * Math.sin(Math.toRadians(angle)));
MovingVector movingVector = new MovingVector(x, y);
return movingVector;
}
private Coordinates randomizeCoordinates() {
Double random = Math.random();
Coordinates randomizedCoordinates;
int xPos;
int yPos;
if(random < 0.25) {
xPos = (int) ballSpawnFrame.getXBeginning();
yPos = (int)(Math.random()*ballSpawnFrame.getYEnding());
} else if(random >= 0.25 && random < 0.50) {
xPos = (int)(Math.random()*ballSpawnFrame.getXEnding());
yPos = (int) ballSpawnFrame.getYBeginning();
} else if(random >= 0.50 && random < 0.75) {
xPos = (int) ballSpawnFrame.getXEnding();
yPos = (int) (Math.random()*ballSpawnFrame.getYEnding());
} else {
xPos = (int) (Math.random()*ballSpawnFrame.getXEnding());
yPos = (int) ballSpawnFrame.getYEnding();
}
randomizedCoordinates = new Coordinates(xPos, yPos);
return randomizedCoordinates;
}
public BlueBall[] getBlueBalls() {
return blueBalls;
}
public void mousePressed(Point pressedPointOnScreen) {
if(!gameStarted) {
if(pressedPointOnScreen.x < gamePanelWidth /2 + ballSize/2 && gamePanelWidth /2 – ballSize/2 < pressedPointOnScreen.x
&& pressedPointOnScreen.y < gamePanelHeight/2 + ballSize/2 && pressedPointOnScreen.y > gamePanelHeight/2 – ballSize/2) {
startGame();
}
}
}
public Player getPlayer() {
return player;
}
}
Coordinates.java
public class Coordinates {
private double xPos;
private double yPos;
public Coordinates(double x, double y) {
this.xPos = x;
this.yPos = y;
}
public double getxPos() {
return xPos;
}
public double getyPos() {
return yPos;
}
}
Difficulty.java
public class Difficulty {
String name;
int numberOfObstacles;
double obstaclesMovingSpeed;
public Difficulty(String name, int numberOfObstacles, double obstaclesMovingSpeed) {
this.name = name;
this.numberOfObstacles = numberOfObstacles;
this.obstaclesMovingSpeed = obstaclesMovingSpeed;
}
public int getNumberOfObstacles() {
return numberOfObstacles;
}
public double getObstaclesMovingSpeed() {
return obstaclesMovingSpeed;
}
}
InformationBar.java
import java.awt.*;
import java.util.concurrent.TimeUnit;
public class InformationBar {
int width;
int height;
int currentHealthPoints;
int maxHealthPoints;
long gameStartedTimeStamp;
public InformationBar(int width, int height, int maxHealthPoints) {
this.width = width;
this.height = height;
this.maxHealthPoints = maxHealthPoints;
currentHealthPoints = maxHealthPoints;
}
public void draw(Graphics g) {
g.setColor(Color.gray);
g.drawRect(5, 5, width, height);
g.setColor(Color.GREEN);
g.fillRect(5, 5, (int)(((double) currentHealthPoints / maxHealthPoints) * width), height);
g.setFont(new Font(“TimesRoman”, Font.BOLD, 15));
g.drawString(Integer.toString(currentHealthPoints), width + 15, height);
g.drawString(String.format(“Playing time: %02d : %02d”,
TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() – gameStartedTimeStamp),
TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() – gameStartedTimeStamp) –
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() – gameStartedTimeStamp))
), width + 100, height);
}
public void setCurrentHealthPoints(int points) {
currentHealthPoints = points;
}
public int getCurrentHealthPoints() {
return currentHealthPoints;
}
public void setGameStartedTimeStamp(long gameStartedTimeStamp) {
this.gameStartedTimeStamp = gameStartedTimeStamp;
}
public long getGameStartedTimeStamp() {
return gameStartedTimeStamp;
}
}
Main.java
import javax.swing.*;
public class Main {
public static void main(String[] args) {
new MenuGUI();
}
}
MainGamePanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class MainGamePanel extends JPanel {
private InformationBar informationBar;
private BoardController boardController;
@Override
public void addNotify() {
super.addNotify();
requestFocus();
}
public MainGamePanel(JFrame parent, Difficulty gameDifficulty) {
super();
this.setLayout(new BorderLayout());
this.validate();
informationBar = new InformationBar(180, 20, 120);
boardController = new BoardController(parent, this, gameDifficulty, 500, 500, 10);
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.black);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Point pressedPointOnScreen = e.getPoint();
boardController.mousePressed(pressedPointOnScreen);
}
});
}
public void refreshView() {
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
paintPlayer(g);
if(boardController.getBlueBalls() != null) {
paintBalls(g);
}
paintHealthBar(g);
}
private void paintHealthBar(Graphics g) {
informationBar.draw(g);
}
private void paintPlayer(Graphics g) {
Player player = boardController.getPlayer();
player.draw(g);
}
private void paintBalls(Graphics g) {
BlueBall[] blueBalls = boardController.getBlueBalls();
for(int i = 0; i< blueBalls.length; i++) {
blueBalls[i].draw(g);
}
}
public InformationBar getInformationBar() {
return informationBar;
}
}
MenuGUI.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuGUI extends JFrame {
private JButton easyLevelButton = new JButton(“Easy”);
private JButton mediumLevelButton = new JButton(“Medium”);
private JButton hardLevelButton = new JButton(“Hard”);
private JLabel instructionsLabel = new JLabel(“Please select difficulty and then in next window click on red ball to strat game!”);
public MenuGUI() {
createPanel();
this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
easyLevelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Difficulty gameDifficulty = new Difficulty(“easy”, 20, 5);
startGame(gameDifficulty);
}
});
mediumLevelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Difficulty gameDifficulty = new Difficulty(“medium”, 30, 7);
startGame(gameDifficulty);
}
});
hardLevelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Difficulty gameDifficulty = new Difficulty(“hard”, 45, 10);
startGame(gameDifficulty);
}
});
}
private void createPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weighty = 0.1;
panel.add(instructionsLabel, c);
c.gridy = 1;
panel.add(easyLevelButton, c);
c.gridy = 2;
panel.add(mediumLevelButton, c);
c.gridy = 3;
panel.add(hardLevelButton, c);
this.setTitle(“Select Level.”);
this.add(panel);
this.setSize(300, 270);
this.setResizable(false);
this.setVisible(true);
}
public void startGame(Difficulty gameDifficulty) {
JFrame f = new JFrame(“Java Dodge Game”);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MainGamePanel mainGamePanel = new MainGamePanel(f, gameDifficulty);
f.add(mainGamePanel);
f.setSize(507,505);
f.setVisible(true);
f.setResizable(false);
this.setVisible(false);
}
}
MovingVector.java
public class MovingVector {
private double x;
private double y;
public MovingVector(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
Player.java
import java.awt.*;
public class Player {
Coordinates coordinates;
final Color bodyColor;
public Player(Coordinates coordinates) {
this.coordinates = coordinates;
this.bodyColor = Color.RED;
}
public Coordinates getCoordinates() {
return coordinates;
}
public void draw(Graphics g) {
g.setColor(bodyColor);
g.drawOval((int)coordinates.getxPos() – 5, (int)coordinates.getyPos() – 5, 10, 10);
g.fillOval((int)coordinates.getxPos() – 5, (int)coordinates.getyPos()- 5, 10, 10);
}
public void moveByVector(MovingVector movingVector) {
double xPos = coordinates.getxPos() + movingVector.getX();
double yPos = coordinates.getyPos() + movingVector.getY();
coordinates = new Coordinates(xPos, yPos);
}
}