0% found this document useful (0 votes)
11 views

Game

Uploaded by

Sharath Reddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Game

Uploaded by

Sharath Reddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 7

import javax.swing.

*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.IntStream;

class BubbleUtil {
private static final int BUBBLE_SIZE = 50;

public static Point findValidRandomNeighbor(int index, int neighborhoodSize,


JPanel gamePanel, List<Point> bubbleOrigins, List<Point> fixedOrigins) {
if(index >= bubbleOrigins.size())
return null;
Random random = new Random();
Point origin = fixedOrigins.get(index);
int left = Math.max(0, origin.x - neighborhoodSize + BUBBLE_SIZE / 2);
int bottom = Math.max(0, origin.y - neighborhoodSize + BUBBLE_SIZE / 2);
int right = Math.min(origin.x + neighborhoodSize - BUBBLE_SIZE / 2,
gamePanel.getWidth() - BUBBLE_SIZE);
int top = Math.min(origin.y + neighborhoodSize - BUBBLE_SIZE / 2,
gamePanel.getHeight() - BUBBLE_SIZE);
Point newOrigin;
do {
int newX = left + random.nextInt(right - left + 1);
int newY = bottom + random.nextInt(top - bottom + 1);
newOrigin = new Point(newX, newY);
} while (!isValidBubblePlacement(newOrigin, gamePanel, bubbleOrigins,
bubbleOrigins.get(index)));

return newOrigin;
}

public static boolean isValidBubblePlacement(Point origin, JPanel gamePanel,


List<Point> bubbleOrigins, Point oldOrigin) {
return isBubbleWithinPanelBoundaries(origin, gamePanel) && !
isBubbleOverlapping(origin, bubbleOrigins, oldOrigin);
}

private static boolean isBubbleWithinPanelBoundaries(Point point, JPanel


gamePanel) {
return point.getX() > BUBBLE_SIZE / 2
&& point.getY() > BUBBLE_SIZE / 2
&& point.getX() < gamePanel.getWidth() - BUBBLE_SIZE / 2
&& point.getY() < gamePanel.getHeight() - BUBBLE_SIZE / 2;
}

private static boolean isBubbleOverlapping(Point origin, List<Point>


bubbleOrigins, Point oldOrigin) {
for (Point otherOrigin : bubbleOrigins) {
if (otherOrigin != null && (oldOrigin == null ||
otherOrigin.distance(oldOrigin) != 0) && otherOrigin.distance(origin) <
BUBBLE_SIZE) {
return true;
}
}
return false;
}
}

class RepositionBubbles implements Runnable {


private final Random random = new Random();
private final int BUBBLE_SIZE;
private final int CURR_ROUND;
private final List<Point> BUBBLE_ORIGINS;
private final JPanel GAME_PANEL;
private final List<Point> FIXED_ORIGINS;
RepositionBubbles(int bubbleSize, int currRound, List<Point> bubbleOrigins,
JPanel gamePanel, List<Point> fixedBubbleOriginsAtRoundStart) {
BUBBLE_SIZE = bubbleSize;
CURR_ROUND = currRound;
BUBBLE_ORIGINS = bubbleOrigins;
GAME_PANEL = gamePanel;
FIXED_ORIGINS = fixedBubbleOriginsAtRoundStart;
}

@Override
public void run() {
int neighborhoodSize = BUBBLE_SIZE + 18 * (CURR_ROUND == 0 ? 1 : CURR_ROUND
- 1);
List<Point> tempOrigins = new ArrayList<>();
for(Point origin: BUBBLE_ORIGINS) {
tempOrigins.add(new Point(origin));
}
while (!Thread.currentThread().isInterrupted() && !
BUBBLE_ORIGINS.isEmpty()) {
for (int i = 0; i < BUBBLE_ORIGINS.size(); i++) {
Point origin;
if((origin = BubbleUtil.findValidRandomNeighbor(i,
neighborhoodSize, GAME_PANEL, BUBBLE_ORIGINS, FIXED_ORIGINS)) != null && !
BUBBLE_ORIGINS.isEmpty())
BUBBLE_ORIGINS.set(i, origin);
}
try {
Thread.sleep(3000);
GAME_PANEL.repaint();
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
}
}

public class Game extends JPanel {


private final JFrame mainMenuFrame;
private JFrame playAreaFrame;
private JPanel playAreaPanel;
private final JSlider difficultySlider;
private int selectedBubbleCount;
private int currentBubbleCount;
private int currentRound;
private JButton startGameButton;
private JButton restartGameButton;
private static final int BUBBLE_SIZE = 50;
private List<Point> bubbleOrigins;
private List<Point> fixedBubbleOriginsAtRoundStart;
private Timer gameTimer;
private final Random randomGenerator = new Random();
private static Thread animationThread;
private boolean gameIsWon;

public static void main(String[] args) {


new Game();
}

public Game() {
mainMenuFrame = new JFrame("Let's Play");

startGameButton = new JButton("Start");


restartGameButton = new JButton("Restart");
difficultySlider = createDifficultySlider();

startGameButton.addActionListener(event -> startNewGame());


restartGameButton.addActionListener(event -> restartGame());

JPanel buttonsPanel = new JPanel(new FlowLayout());


buttonsPanel.add(startGameButton);
buttonsPanel.add(restartGameButton);

JPanel menuPanel = new JPanel(new BorderLayout());


menuPanel.add(difficultySlider, BorderLayout.NORTH);
menuPanel.add(buttonsPanel, BorderLayout.SOUTH);

mainMenuFrame.add(menuPanel);
mainMenuFrame.setSize(500, 250);
mainMenuFrame.setVisible(true);
mainMenuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private JSlider createDifficultySlider() {


JSlider slider = new JSlider(SwingConstants.VERTICAL, 4, 6, 5);
slider.setToolTipText("Select Difficulty");
slider.setLabelTable(new Hashtable<Integer, JLabel>() {{
put(4, new JLabel("4 Bubbles"));
put(5, new JLabel("5 Bubbles"));
put(6, new JLabel("6 Bubbles"));
}});
slider.setMinorTickSpacing(1);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
return slider;
}

private void startNewGame() {


resetGame();

selectedBubbleCount = difficultySlider.getValue();
playAreaFrame = new JFrame("Bubble Burst Game - Round: " + (currentRound +
1));
playAreaFrame.setSize(600, 600);
playAreaFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
playAreaPanel = createGamePanel();
playAreaFrame.add(playAreaPanel);
playAreaFrame.setVisible(true);
mainMenuFrame.setVisible(false);

showBubblePlacementGuide();
}

private JPanel createGamePanel() {


JPanel panel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawOrigins(g);
}
};
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {
if (currentRound == 0) {
setBubbleOrigins(event);
} else {
handleClick(event);
}
}
});
return panel;
}

private void showBubblePlacementGuide() {


JOptionPane.showMessageDialog(playAreaPanel, "Define the origin for each
bubble");
}

private void drawOrigins(Graphics g) {


for (Point bubble : bubbleOrigins) {
g.setColor(Color.BLACK);
g.fillOval(bubble.x - (BUBBLE_SIZE / 2), bubble.y - (BUBBLE_SIZE / 2),
BUBBLE_SIZE, BUBBLE_SIZE);
}
if(fixedBubbleOriginsAtRoundStart != null)
drawNeighborhood(g);
}

public void drawNeighborhood(Graphics g) {


for(int i=0; i < fixedBubbleOriginsAtRoundStart.size(); i++) {
Point pt = fixedBubbleOriginsAtRoundStart.get(i);
int neighborhoodSize = BUBBLE_SIZE + 18 * (currentRound == 0 ? 0 :
currentRound - 1);
int topLeftX = pt.x - neighborhoodSize;
int topLeftY = pt.y - neighborhoodSize;

// Generate random color


Color randomColor = new Color(Math.abs(randomGenerator.nextInt()) %
255, Math.abs(randomGenerator.nextInt()) % 255,Math.abs(randomGenerator.nextInt())
% 255);

// Set the drawing color


g.setColor(randomColor);

g.drawRect(topLeftX, topLeftY, neighborhoodSize * 2, neighborhoodSize *


2);
}
}

private void setBubbleOrigins(MouseEvent event) {


if (currentBubbleCount < selectedBubbleCount) {
Point clickedPoint = event.getPoint();
if (BubbleUtil.isValidBubblePlacement(clickedPoint, playAreaPanel,
bubbleOrigins, null)) {
currentBubbleCount++;
fixedBubbleOriginsAtRoundStart.add(clickedPoint);
bubbleOrigins.add(clickedPoint);
playAreaPanel.repaint();
if (currentBubbleCount == selectedBubbleCount) {
proceedToNextRound();
}
} else {
JOptionPane.showMessageDialog(playAreaPanel, "Bubble must be fully
within the panel and not overlap others.");
}
}
}

private void proceedToNextRound() {


stopTimer();
currentRound++;
int currentRoundDuration = 15 - currentRound;
if (currentRound <= 10) {
playAreaFrame.setTitle("Round-"+ currentRound+", Time
Left:"+currentRoundDuration+" seconds");
startTimer(currentRoundDuration);
if (currentRound > 1) {
repositionGlobal();
}
if (bubbleOrigins.size() == selectedBubbleCount) {
repositionLocal();
}
} else {
handleGameOver(JOptionPane.INFORMATION_MESSAGE, "You Won, Congrats!");
}
}

private void startTimer(final int currentRoundDuration) {


ActionListener listener = new ActionListener() {
int timeLeft = currentRoundDuration;
@Override
public void actionPerformed(ActionEvent e) {
timeLeft--;
playAreaFrame.setTitle("Round-"+ currentRound+", Time
Left:"+timeLeft+" seconds");
if (timeLeft <= 0 && gameTimer.isRunning()) {
handleGameOver(JOptionPane.ERROR_MESSAGE, "You failed to burst
all bubbles before time is over, try again!");
}
}
};
gameTimer = new Timer(1000, listener);
gameTimer.start();
}

private void stopTimer() {


if(gameTimer != null)
gameTimer.stop();
}

private void handleGameOver(int messageType, String msg) {


stopTimer();
animationThread.interrupt();
JOptionPane.showMessageDialog(playAreaPanel, msg, "Game Over",
messageType);
playAreaFrame.setVisible(false);
startGameButton.setVisible(false);
restartGameButton.setEnabled(true);
mainMenuFrame.setVisible(true);
}

private void repositionLocal() {


if(animationThread != null) animationThread.interrupt();
RepositionBubbles repositionBubbles = new RepositionBubbles(BUBBLE_SIZE,
currentRound, bubbleOrigins, playAreaPanel, fixedBubbleOriginsAtRoundStart);
animationThread = new Thread(repositionBubbles);
animationThread.start();
}

private void repositionGlobal() {


IntStream.range(0, selectedBubbleCount)
.mapToObj(index -> createNonOverlappingBubble())
.forEach(origin -> {
bubbleOrigins.add(origin);
fixedBubbleOriginsAtRoundStart.add(origin);
});
playAreaPanel.repaint();
bubbleOrigins = new ArrayList<>(fixedBubbleOriginsAtRoundStart);
}

private Point createNonOverlappingBubble() {


Point bubble;
do {
bubble = new Point(randomGenerator.nextInt(playAreaPanel.getWidth() -
BUBBLE_SIZE),
randomGenerator.nextInt(playAreaPanel.getHeight() -
BUBBLE_SIZE));
} while (!BubbleUtil.isValidBubblePlacement(bubble, playAreaPanel,
bubbleOrigins, null));
return bubble;
}

private void handleClick(MouseEvent event) {


Point clickedPoint = event.getPoint();
int selectedIndex = -1;
for (int i=0; i < bubbleOrigins.size(); i++) {
Point origin = bubbleOrigins.get(i);
if (origin.distance(clickedPoint) <= BUBBLE_SIZE) {
selectedIndex = i;
break;
}
}
if (selectedIndex != -1) {
bubbleOrigins.remove(selectedIndex);
fixedBubbleOriginsAtRoundStart.remove(selectedIndex);
playAreaPanel.repaint();

if (bubbleOrigins.isEmpty()) {
if (animationThread != null) {
animationThread.interrupt();
}
if (currentRound < 10) {
proceedToNextRound();
} else {
gameIsWon = true;
handleGameOver(JOptionPane.INFORMATION_MESSAGE, "You Won,
Congrats!");
}
}
}
else {
gameIsWon = false;
handleGameOver(JOptionPane.ERROR_MESSAGE, "You Lost as you didn't click
on bubble, try again");
}
}

private void resetGame() {


gameIsWon = false;
currentRound = 0;
currentBubbleCount = 0;
bubbleOrigins = new CopyOnWriteArrayList<>();
fixedBubbleOriginsAtRoundStart = new ArrayList<>();
}

private void restartGame() {


System.out.println("Resetting the game");
startNewGame();
}

You might also like