I want to add a simple menu to my Java Snake game which will contain three buttons (New Game, Difficulty and Quit). I have created a class for the menu and a class for the mouse input. I have used an enum to store the states of the game (MAIN_MENU, DIFFICULTY_MENU and GAME) and a variable called STATE which stores the current state.
The main problem is that although the state of the game is changed when the "New Game" button is pressed the game doesn't start. I have tried to add game state checks inside the methods that are involved in setting the gameplay and I have also tried calling those methods from the mousePressed() method of the MouseInput class but none of these worked.
I would greatly appreciate if you could give me some tips on how to solve this issue.
Here's my code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SnakeGame extends JFrame{
public SnakeGame() {
initGUI();
}
public void initGUI() {
add(new GamePlay());
setResizable(false);
pack();
setTitle("The Snake");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new SnakeGame();
frame.setVisible(true);
});
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class GamePlay extends JPanel implements ActionListener {
public static final int HEIGHT = 600;
public static final int WIDTH = 600;
private final int TOTAL_DOTS = 3600;
private final int DOT_SIZE = 10;
private final int RAND_POSITION = 29;
//private final int DELAY = 140;
private final int[] X = new int[TOTAL_DOTS];// the dots on X axis
private final int[] Y = new int[TOTAL_DOTS];//the dots on Y axis
private int dots;
private int apple_X;
private int apple_Y;
private int score = 0;
private int DELAY = 140;
private boolean leftDirection = false;
private boolean rightDirection = true;
private boolean upDirection = false;
private boolean downDirection = false;
private boolean inGame = true;
private Timer timer;
private Image bodyPart;
private Image snakeHead;
private Image apple;
private Menu menu;
public static GameState STATE = GameState.MAIN_MENU;//current game state(it changes when menu buttons are pressed)
public static enum GameState{
MAIN_MENU,
DIFFICULTY_MENU,
GAME
}
public GamePlay() {
setGamePlay();
}
public void setGamePlay() {
addKeyListener(new KeyboardEvent());
addMouseListener(new MouseInput());
setBackground(Color.BLACK);
setFocusable(true);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
if(STATE == GameState.GAME) {
loadImages();
startGame();
}
}
private void loadImages() {
ImageIcon img2 = new ImageIcon("src/images/dot.png");
bodyPart = img2.getImage();
ImageIcon img1 = new ImageIcon("src/images/head.png");
snakeHead = img1.getImage();
ImageIcon img3 = new ImageIcon("src/images/apple.png");
apple = img3.getImage();
}
//setting the starting snake length and the apple position on the board
public void startGame() {
dots = 3;
for(int i = 0 ; i < dots; i++) {
X[i] = 50 - i * 10;
Y[i] = 50;
}
locateApple();
timer = new Timer(DELAY,this);
//timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(STATE == GameState.GAME) {
draw(g);
}else if(STATE == GameState.MAIN_MENU) {
new Menu().displayMainMenu(g);
}else if(STATE == GameState.DIFFICULTY_MENU) {
new Menu().displayDifficultyMenu(g);
}
System.out.println("End of paint component method");
}
public void draw(Graphics g) {
scoreDisplay(g);
if(inGame) {
g.drawImage(apple, apple_X, apple_Y,this);
for(int i = 0 ; i < dots; i++) {
if(i == 0) {
g.drawImage(snakeHead,X[i], Y[i], this);
}else {
g.drawImage(bodyPart, X[i], Y[i], this);
}
}
Toolkit.getDefaultToolkit().sync();
}else {
gameOver(g);
}
}
public void gameOver(Graphics g) {
String msg = "Game Over!";
String msg2 = "Score: " + score + " " + "Length: " + dots;
Font small = new Font("Comic Sans",Font.BOLD,14 );
FontMetrics messageSize = getFontMetrics(small);
g.setColor(Color.WHITE);
g.setFont(small);
g.drawString(msg, (WIDTH - messageSize.stringWidth(msg)) / 2, HEIGHT / 2);
g.drawString(msg2, (WIDTH - messageSize.stringWidth(msg2)) / 2, (HEIGHT / 2) + 20);
restartMessageDisplay(g);
}
public void scoreDisplay(Graphics g) {
String gameScore = "Score: " + score;
String snakeLength = "Snake length: " + dots;
Font small = new Font("Arial", Font.BOLD, 14);
g.setColor(Color.WHITE);
g.setFont(small);
g.drawString(gameScore,480, 20);
g.drawString(snakeLength, 480, 40);
}
public void restartMessageDisplay(Graphics g) {
String restartMessage = " Press Enter to restart";
Font small = new Font("Arial", Font.BOLD, 14);
FontMetrics metrics = getFontMetrics(small);
g.drawString(restartMessage, (WIDTH - metrics.stringWidth(restartMessage)) / 2, (HEIGHT / 2) + 40);
}
private void checkApple() {
if((X[0] == apple_X) && (Y[0] == apple_Y)) {
dots++;
locateApple();
score += 5;//score update
DELAY -= 5;// speed increase when snake eats the apple
if(DELAY >= 40) {
timer.setDelay(DELAY);
}
}
}
//snake move logic
private void move() {
for(int i = dots; i > 0; i--) {
X[i] = X[(i-1)];
Y[i] = Y[(i-1)];
}
if(leftDirection) {
X[0] -= DOT_SIZE;
}
if(rightDirection) {
X[0] += DOT_SIZE;
}
if(upDirection) {
Y[0] -= DOT_SIZE;
}
if(downDirection) {
Y[0] += DOT_SIZE;
}
}
//checking for collision with the walls or the snake itself
private void checkCollision() {
for(int i = dots; i > 0; i--) {
if((i > 4) && (X[0] == X[i]) && (Y[0] == Y[i])) {
inGame = false;
}
}
if(X[0] < 0) {
inGame = false;
}
if(X[0] > WIDTH) {
inGame = false;
}
if(Y[0] < 0) {
inGame = false;
}
if(Y[0] > HEIGHT) {
inGame = false;
}
if(!inGame) {
timer.stop();
}
}
//setting apple position on the board
public void locateApple() {
int random = (int) (Math.random() * RAND_POSITION);
apple_X = random * DOT_SIZE;
random = (int) (Math.random()* RAND_POSITION);
apple_Y = random * DOT_SIZE;
}
#Override
public void actionPerformed(ActionEvent e) {
if(inGame) {
checkApple();
checkCollision();
move();
}
repaint();
}
private class KeyboardEvent extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if((keyCode == KeyEvent.VK_LEFT) && (!rightDirection)) {
leftDirection = true;
upDirection = false;
downDirection = false;
}
if((keyCode == KeyEvent.VK_RIGHT) && (!leftDirection)) {
rightDirection = true;
upDirection = false;
downDirection = false;
}
if((keyCode == KeyEvent.VK_UP) && (!downDirection)) {
upDirection = true;
leftDirection = false;
rightDirection = false;
}
if((keyCode == KeyEvent.VK_DOWN) && (!upDirection)) {
downDirection = true;
leftDirection = false;
rightDirection = false;
}
if(keyCode == KeyEvent.VK_PAUSE) {
timer.stop();
}
if(keyCode == KeyEvent.VK_SPACE) {
timer.start();
}
//game restart
if(keyCode == KeyEvent.VK_ENTER) {
if(!inGame) {
inGame = true;
leftDirection = false;
rightDirection = true;
upDirection = false;
downDirection = false;
score = 0;
DELAY = 140;
setGamePlay();
repaint();
}
}
}
}
}
import java.awt.*;
import javax.swing.*;
public class Menu {
public Rectangle newGameButton;
public Rectangle gameDifficultyButton;
public Rectangle quitButton;
public Rectangle easyDifficultyButton;
public Rectangle mediumDifficultyButton;
public Rectangle hardDifficultyButton;
public Button button1;
public Menu() {
int buttonWidth = 150;
int buttonHeight = 50;
newGameButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) - 50, buttonWidth, buttonHeight);
gameDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 50, buttonWidth, buttonHeight);
quitButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 150, buttonWidth, buttonHeight);
easyDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) - 50, buttonWidth, buttonHeight);
mediumDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 50, buttonWidth, buttonHeight);
hardDifficultyButton = new Rectangle((GamePlay.WIDTH - buttonWidth) / 2, (GamePlay.HEIGHT / 2) + 150, buttonWidth, buttonHeight);
}
public void displayMainMenu(Graphics g) {
Graphics2D buttonGraphics =(Graphics2D) g;
String title = "THE SNAKE GAME";
Font font = new Font("Arial", Font.BOLD, 50);
FontMetrics size = g.getFontMetrics(font);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(title,(GamePlay.WIDTH-size.stringWidth(title)) / 2, (GamePlay.HEIGHT / 2) - 130);
Font buttonFont = new Font("Arial", Font.BOLD, 28);
g.setFont(buttonFont);
g.drawString("New Game",newGameButton.x + 2, newGameButton.y + 35);
buttonGraphics.draw(newGameButton);
g.drawString("Difficulty",gameDifficultyButton.x + 15,gameDifficultyButton.y + 35);
buttonGraphics.draw(gameDifficultyButton);
g.drawString("Quit", quitButton.x + 45, quitButton.y + 35);
buttonGraphics.draw(quitButton);
}
public void displayDifficultyMenu(Graphics g) {
Graphics2D difficultyMenuGraphics = (Graphics2D) g;
String title = "Difficulty level";
Font difficultyMenuTitleFont = new Font("Arial", Font.BOLD,40);
FontMetrics size = g.getFontMetrics(difficultyMenuTitleFont);
g.setFont(difficultyMenuTitleFont);
g.setColor(Color.WHITE);
g.drawString(title, (GamePlay.WIDTH - size.stringWidth(title)) / 2, (GamePlay.HEIGHT / 2) - 100);
Font difficultyButtonFont = new Font("Arial", Font.BOLD, 28);
g.setFont(difficultyButtonFont);
g.drawString("Easy", easyDifficultyButton.x + 40 , easyDifficultyButton.y + 35);
difficultyMenuGraphics.draw(easyDifficultyButton);
g.drawString("Medium",mediumDifficultyButton.x + 20, mediumDifficultyButton.y + 35);
difficultyMenuGraphics.draw(mediumDifficultyButton);
g.drawString("Hard", hardDifficultyButton.x + 40, hardDifficultyButton.y + 35);
difficultyMenuGraphics.draw(hardDifficultyButton);
}
}
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.Thread.State;
public class MouseInput extends MouseAdapter {
public Rectangle newGameButton;
public Rectangle gameDifficultyButton;
public Rectangle quitButton;
public Rectangle easyDifficultyButton;
public Rectangle mediumDifficultyButton;
public Rectangle hardDifficultyButton;
Graphics g;
public void mousePressed(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
//NewGame button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150) / 2) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) - 50 && mouseY <= (GamePlay.HEIGHT/ 2)) {
GamePlay.STATE = GamePlay.GameState.GAME;
System.out.println(GamePlay.STATE);
}
}
//Difficulty button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150)/ 2 ) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) + 50 && mouseY <= (GamePlay.HEIGHT/ 2) + 100) {
GamePlay.STATE = GamePlay.STATE.DIFFICULTY_MENU;
System.out.println("Game state = " + GamePlay.STATE)
}
}
//Quit button
if(mouseX >= (GamePlay.WIDTH - 150) / 2 && mouseX <= ((GamePlay.WIDTH - 150)/ 2 ) + 150) {
if(mouseY >= (GamePlay.HEIGHT / 2) + 150 && mouseY <= (GamePlay.HEIGHT/ 2) + 200) {
System.exit(0);
}
}
}
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 months ago.
Improve this question
I'm a beginner so I used Bro Code's (a YouTuber) version of snake game. It's almost identical with minor adjustments, but I've been trying to figure out how to restart the game when I die. I've tried making a restart button and tried to make it restart with a keystroke but I've got no experience coding so I couldn't figure it out. Here's the source code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel<Restart> extends JPanel implements ActionListener {
static final int SCREEN_WIDTH = 1300;
static final int SCREEN_HEIGHT = 750;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / (UNIT_SIZE * UNIT_SIZE);
static final int DELAY = 85;
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 5;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random;
GamePanel() {
random = new Random();
this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame() {
newApple();
running = true;
timer = new Timer(DELAY, this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
/*
* for(int i=0;i<SCREEN_HEIGHT/UNIT_SIZE;i++) { g.drawLine(i*UNIT_SIZE, 0,
* i*UNIT_SIZE, SCREEN_HEIGHT); g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH,
* i*UNIT_SIZE); }
*/
g.setColor(Color.red);
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
for (int i = 0; i < bodyParts; i++) {
if (i == 0) {
g.setColor(Color.green);
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
else {
g.setColor(new Color(45, 180, 0));
// g.setColor(new
// Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
}
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten,
(SCREEN_WIDTH - metrics.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
}
else {
gameOver(g);
}
}
public void newApple() {
appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
}
public void move() {
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}
switch (direction) {
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
}
public void checkApple() {
if ((x[0] == appleX) && (y[0] == appleY)) {
bodyParts++;
applesEaten++;
newApple();
}
}
public void checkCollisions() {
// checks if head collides with body
for (int i = bodyParts; i > 0; i--) {
if ((x[0] == x[i]) && (y[0] == y[i])) {
running = false;
}
}
// check if head touches left border
if (x[0] < 0) {
running = false;
}
// check if head touches right border
if (x[0] > SCREEN_WIDTH) {
running = false;
}
// check if head touches top border
if (y[0] < 0) {
running = false;
}
// check if head touches bottom border
if (y[0] > SCREEN_HEIGHT) {
running = false;
}
if (!running) {
timer.stop();
}
}
public void gameOver(Graphics g) {
// Score
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten,
(SCREEN_WIDTH - metrics1.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
// Game Over text
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over")) / 2,
SCREEN_HEIGHT / 2);
}
#Override
public void actionPerformed(ActionEvent e) {
if (running) {
move();
checkApple();
checkCollisions();
}
repaint();
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_A:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_D:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_W:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_S:
if (direction != 'U') {
direction = 'D';
}
}
}
}
}
This is the solution, Pressing Enter will close the previous window and open a new game window. Let me know if you don't understand something so I can explain it to you!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public final class GamePanel<Restart> extends JPanel implements ActionListener {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
static final int SCREEN_WIDTH = 1300;
static final int SCREEN_HEIGHT = 750;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / (UNIT_SIZE * UNIT_SIZE);
static final int DELAY = 85;
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 5;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random;
public void createGUI() {
panel.add(new GamePanel());
frame.add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
GamePanel() {
random = new Random();
setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
setBackground(Color.black);
setFocusable(true);
addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame() {
newApple();
running = true;
timer = new Timer(DELAY, this);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
/*
* for(int i=0;i<SCREEN_HEIGHT/UNIT_SIZE;i++) { g.drawLine(i*UNIT_SIZE, 0,
* i*UNIT_SIZE, SCREEN_HEIGHT); g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH,
* i*UNIT_SIZE); }
*/
g.setColor(Color.red);
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
for (int i = 0; i < bodyParts; i++) {
if (i == 0) {
g.setColor(Color.green);
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
} else {
g.setColor(new Color(45, 180, 0));
// g.setColor(new
// Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
}
}
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten,
(SCREEN_WIDTH - metrics.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
} else {
gameOver(g);
}
}
public void newApple() {
appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
}
public void move() {
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i - 1];
y[i] = y[i - 1];
}
switch (direction) {
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
}
public void checkApple() {
if ((x[0] == appleX) && (y[0] == appleY)) {
bodyParts++;
applesEaten++;
newApple();
}
}
public void checkCollisions() {
// checks if head collides with body
for (int i = bodyParts; i > 0; i--) {
if ((x[0] == x[i]) && (y[0] == y[i])) {
running = false;
}
}
// check if head touches left border
if (x[0] < 0) {
running = false;
}
// check if head touches right border
if (x[0] > SCREEN_WIDTH) {
running = false;
}
// check if head touches top border
if (y[0] < 0) {
running = false;
}
// check if head touches bottom border
if (y[0] > SCREEN_HEIGHT) {
running = false;
}
if (!running) {
timer.stop();
}
}
public void gameOver(Graphics g) {
// Score
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Score: " + applesEaten,
(SCREEN_WIDTH - metrics1.stringWidth("Score: " + applesEaten)) / 2,
g.getFont().getSize());
// Game Over text
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over")) / 2,
SCREEN_HEIGHT / 2);
}
#Override
public void actionPerformed(ActionEvent e) {
if (running) {
move();
checkApple();
checkCollisions();
}
repaint();
}
public void closeRunningWindow(KeyEvent e) {
JComponent comp = (JComponent) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose();
}
public void startAgain() {
EventQueue.invokeLater(() -> {
GamePanel game = new GamePanel();
game.createGUI();
});
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_A:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_D:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_W:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_S:
if (direction != 'U') {
direction = 'D';
}
break;
case KeyEvent.VK_ENTER:
closeRunningWindow(e);
startAgain();
break;
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
GamePanel game = new GamePanel();
game.createGUI();
});
}
}
I am build a graph, with a while circle moving along a line, and stoping over for a few seconds at 3 points of the path.
I have managed to do it, however, it does not display the circle moving, it displays only when the circle stops...
I can't understand why.
Many thanks in advance for your help
Here is my code:
public class Robot0 extends JFrame implements ActionListener {
public Robot0(String nom, int larg, int haut) {
setTitle(nom);
setSize(larg, haut);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
Timer tm = new Timer(10, this);
private int posX = 0;
private int posY = 0;
private int velX = 1;
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
// Draw the pathway
int xt[] = { 50, 50, 250, 250, 350, 350 };
int yt[] = { 50, 150, 150, 50, 50, 150 };
g.drawPolyline(xt, yt, 6);
// On the pathway, draw 3 squares (the 3 rooms)
g.setColor(Color.GREEN);
g.drawRect(35, 135, 30, 30);
g.drawRect(235, 35, 30, 30);
g.drawRect(335, 135, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(40 + posX, 40 + posY, 20, 20);
g.setColor(Color.RED);
g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);
tm.start();
}
int segment = 0;
public void actionPerformed(ActionEvent e) {
// move along the 1st segment
if (posY < 100 && segment == 0) {
setPosY(posY + velX);
}
if (posY == 100 && posX == 0) {
segment = 1;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
// move along the second segment
if (posX <= 200 && segment == 1) {
setPosX(posX + velX);
}
if (posX == 200 && posY == 100) {
segment = 2;
}
// move along the third segment
if (posY > 0 && segment == 2) {
setPosY(posY - velX);
}
if (posX == 200 && posY == 0) {
segment = 3;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
// move along the fourth segment
if (posX < 300 && segment == 3) {
setPosX(posX + velX);
}
if (posX == 300 && posY == 0) {
segment = 4;
}
// move along the fifth segment
if (posY < 100 && segment == 4) {
setPosY(posY + velX);
}
if (posX == 300 && posY == 100) {
segment = 6;
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(Robot0.class.getName()).log(Level.SEVERE, null, ex);
}
}
repaint();
}
// Build the Panel
public static void main(String[] args) {
Robot0 r = new Robot0("Robot0", 800, 600);
}
}
Swing is a single Thread library. All painting tasks are executed in the Event Dispatcher Thread
(EDT).
As commented by Andrew Thompson, running long processes (such as sleep) on the EDT makes keeps this thread busy, so it does not do other things
like updating the gui.
The gui becomes unresponsive (freezes).
So the first thing to do is to remove all sleeping.
To park at each stop, use a second timer:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Robot0 extends JFrame implements ActionListener {
private static final int PARKING_TIME = 15000;
Timer moveTimer , waitTimer;
private boolean isParking = false;
public Robot0(String nom, int larg, int haut) {
moveTimer = new Timer(10, this);
waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
waitTimer.setRepeats(false);
setTitle(nom);
setSize(larg, haut);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private int posX = 0;
private int posY = 0;
private final int velX = 1;
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.BLACK);
// Draw the pathway
int xt[] = { 50, 50, 250, 250, 350, 350 };
int yt[] = { 50, 150, 150, 50, 50, 150 };
g.drawPolyline(xt, yt, 6);
// On the pathway, draw 3 squares (the 3 rooms)
g.setColor(Color.GREEN);
g.drawRect(35, 135, 30, 30);
g.drawRect(235, 35, 30, 30);
g.drawRect(335, 135, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(40 + posX, 40 + posY, 20, 20);
g.setColor(Color.RED);
g.drawLine(45 + posX, 50 + posY, 55 + posX, 50 + posY);
g.drawLine(50 + posX, 45 + posY, 50 + posX, 55 + posY);
moveTimer.start();
}
int segment = 0;
#Override
public void actionPerformed(ActionEvent e) {
if(isParking) return; //execute only when not parking
// move along the 1st segment
if (posY < 100 && segment == 0) {
setPosY(posY + velX);
}
if (posY == 100 && posX == 0 && segment != 1) { //!=1 so it will not be invoked again
segment = 1;
isParking = true; //flag that robot is parking
waitTimer.start();
return;
}
// move along the second segment
if (posX <= 200 && segment == 1) {
setPosX(posX + velX);
}
if (posX == 200 && posY == 100) {
segment = 2;
}
// move along the third segment
if (posY > 0 && segment == 2) {
setPosY(posY - velX);
}
if (posX == 200 && posY == 0 && segment !=3) {
segment = 3;
isParking = true;
waitTimer.start();
return;
}
// move along the fourth segment
if (posX < 300 && segment == 3) {
setPosX(posX + velX);
}
if (posX == 300 && posY == 0) {
segment = 4;
}
// move along the fifth segment
if (posY < 100 && segment == 4) {
setPosY(posY + velX);
}
if (posX == 300 && posY == 100 && segment !=6) {
segment = 6;
isParking = true;
waitTimer.start();
return;
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new Robot0("Robot0", 800, 600));
}
}
TODO:
Implement custom painting on JPanel.
Simplify actionPerformed
logic
Edit: the following is an implementation with some improvements not necessarily related to question asked:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Robot0 extends JFrame {
public Robot0(String nom) {
setTitle(nom);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new Floor());
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new Robot0("Robot0"));
}
}
class Floor extends JPanel implements ActionListener{
private static final int PARKING_TIME = 5000, REPAINT_TIME = 10, W = 400, H = 200;
private static final int ROOM_SIZE = 30, ROBOT_SIZE = 20, CROSS_SIZE = 10;
private final Timer moveTimer , waitTimer;
private boolean isParking = false;
private int posX = 0, posY = 0;
private final int velX = 1;
// pathway
private static final int PATH_X[] = { 50, 50, 250, 250, 350, 350 };
private static final int PATH_Y[] = { 50, 150, 150, 50, 50, 150 };
//rooms
private static final Point[] ROOM_CENTERS = {new Point(PATH_X[1],PATH_Y[1]),
new Point(PATH_X[3],PATH_Y[3]),
new Point(PATH_X[5],PATH_Y[5]) };
Floor() {
moveTimer = new Timer(REPAINT_TIME, this);
waitTimer = new Timer(PARKING_TIME, e-> isParking = false);
waitTimer.setRepeats(false);
posX = PATH_X[0]; posY = PATH_Y[0];
setPreferredSize(new Dimension(W, H));
moveTimer.start(); //no need to restart with every paint
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawPolyline(PATH_X, PATH_Y, 6);
// draw rooms
g.setColor(Color.GREEN);
for(Point center : ROOM_CENTERS){
drawSquareAround(center, g);
}
//robot
g.setColor(Color.WHITE);
g.fillOval( posX - ROBOT_SIZE/2 , posY - ROBOT_SIZE/2 , ROBOT_SIZE, ROBOT_SIZE);
//cross
g.setColor(Color.RED);
g.drawLine(posX - CROSS_SIZE/2, posY, posX + CROSS_SIZE/2, posY);
g.drawLine(posX, posY - CROSS_SIZE/2, posX, posY + CROSS_SIZE/2);
}
private void drawSquareAround(Point center, Graphics g) {
g.drawRect(center.x - ROOM_SIZE/2, center.y - ROOM_SIZE/2, ROOM_SIZE, ROOM_SIZE);
}
#Override
public void actionPerformed(ActionEvent e) {
if(isParking) return; //execute only when not parking
if (posX <= PATH_X[0] && posY < PATH_Y[1]) {// move along the 1st segment
setPosY(posY + velX);
}else if (posX < PATH_X[2] && posY == PATH_Y[1]) { //move along the second segment
setPosX(posX + velX);
}else if (posX == PATH_X[2] && posY > PATH_Y[3]) { //move along the third segment
setPosY(posY - velX);
}else if (posY == PATH_Y[3] && posX < PATH_X[4]) {// move along the fourth segment
setPosX(posX + velX);
}else if (posX == PATH_X[4] && posY < PATH_Y[5]){// move along the fifth segment
setPosY(posY + velX);
}else {
moveTimer.stop(); //move finished, stop repainting
return;
}
//park if at room center
if(isRoomCeter()){
park();
}
repaint();
}
private void park() {
isParking = true; //flag that robot is parking
waitTimer.start();
}
private boolean isRoomCeter() {
for (Point center : ROOM_CENTERS){
if(posX == center.x && posY == center.y) return true;
}
return false;
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
I have been working on a singleplayer pong game in which you currently use the mouse to control the paddle. I have added key listeners to the frame, and you can move the paddle by hitting the 'a' and 'd' keys, but you cannot hold them down. Here is the code which I have now, and I'd appreciate any help that you can offer!
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
import java.util.concurrent.*;
import java.util.*;
public class Experiment extends JApplet {
public static final int WIDTH = BallRoom.WIDTH;
public static final int HEIGHT = BallRoom.HEIGHT;
public PaintSurface canvas;
public void init()
{
this.setSize(WIDTH, HEIGHT);
canvas = new PaintSurface();
this.add(canvas, BorderLayout.CENTER);
canvas.requestFocusInWindow();
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
}
}
class AnimationThread implements Runnable
{
JApplet c;
public AnimationThread(JApplet c)
{
this.c = c;
}
public void run()
{
c.repaint();
}
}
class PaintSurface extends JComponent implements KeyListener
{
int paddle_x = 0;
int paddle_y = 360;
public boolean aDown;
public boolean dDown;
int score = 0;
float english = 1.0f;
Ball ball;
Color[] color = {Color.RED, Color.ORANGE, Color.MAGENTA, Color.ORANGE, Color.CYAN, Color.BLUE};
boolean aheld = false;
boolean dheld = false;
int colorIndex;
#Override
public void keyTyped(KeyEvent e)
{
System.out.println("Pressed " + e.getKeyChar());
}
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyChar() == 'd')
paddle_x += 10;
if (e.getKeyChar() == 'a')
paddle_x -= 10;
}
#Override
public void keyReleased(KeyEvent e)
{
}
public PaintSurface()
{
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseMoved(MouseEvent e)
{
if (e.getX() - 30 - paddle_x > 5)
english = 1.5f;
else if (e.getX() - 30 - paddle_x < 5)
english = -1.5f;
else
english = 1.0f;
paddle_x = e.getX() - 30;
}
});
addKeyListener(this);
ball = new Ball(20);
}
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
Shape paddle = new Rectangle2D.Float(paddle_x, paddle_y, 60, 8);
g2.setColor(color[colorIndex % 6]);
if (ball.intersects(paddle_x, paddle_y, 60, 8) && ball.y_speed > 0)
{
ball.y_speed = -ball.y_speed * 1.1;
ball.x_speed = ball.x_speed * 1.1;
if (english != 1.0f)
{
colorIndex++;
}
score += Math.abs(ball.x_speed * 10);
}
if (ball.getY() + ball.getHeight() >= BallRoom.HEIGHT)
{
ball = new Ball(20);
score -= 1000;
colorIndex = 0;
}
ball.move();
g2.fill(ball);
g2.setColor(Color.BLACK);
g2.fill(paddle);
g2.drawString("Score: " + score, 250, 20);
}
}
class Ball extends Ellipse2D.Float{
public double x_speed, y_speed;
private int d;
private int width = BallRoom.WIDTH;
private int height = BallRoom.HEIGHT;
public Ball(int diameter)
{
super((int) (Math.random() * (BallRoom.WIDTH - 20) + 1), 0, diameter, diameter);
this.d = diameter;
this.x_speed = (int) (Math.random() * 5) + 1;
this.y_speed = (int) (Math.random() * 5) + 1;
}
public void move()
{
if (super.x < 0 || super.x > width - d)
x_speed = -x_speed;
if (super.y < 0 || super.y > height - d)
y_speed = -y_speed;
super.x += x_speed;
super.y += y_speed;
}
}
runningUse the following code for KeyPressed() and KeyReleased()
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyChar() == 'd')
dheld = true;
if (e.getKeyChar() == 'a')
aheld = true;
}
#Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyChar() == 'd')
dheld = false;
if (e.getKeyChar() == 'a')
aheld = false;
}
Then have method running on a timer that moves the paddle if dheld or aheld are true.
I have the following program, it's a SubKiller game and I have one question. How do I make the boat launch the bomb anytime I press the down key? So far I have made to launch it multiple times. I can launch the first bomb but when I'm trying to launch the second one, the first one disappears and it doesn't continue it's way. I am stuck on this matter for almost two days, help me please.
I am going to provide you the SSCCE code.
This is the class called SubKillerPanel, basically everything is here, the boat is here, the bomb is here, the submarine is here.
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Color;
public class SubKillerPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Timer timer;
private int width, height;
private Boat boat;
private Bomb bomb;
private Submarine sub;
public SubKillerPanel() {
setBackground(Color.WHITE);
ActionListener action = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (boat != null) {
boat.updateForNewFrame();
bomb.updateForNewFrame();
sub.updateForNewFrame();
}
repaint();
}
};
timer = new Timer( 20, action );
addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
requestFocus();
}
}
);
addFocusListener( new FocusListener() {
public void focusGained(FocusEvent evt) {
timer.start();
repaint();
}
public void focusLost(FocusEvent evt) {
timer.stop();
repaint();
}
}
);
addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int code = evt.getKeyCode(); // ce tasta a fost apasata
if (code == KeyEvent.VK_LEFT) {
boat.centerX -= 15;
}
else
if (code == KeyEvent.VK_RIGHT) {
boat.centerX += 15;
}
else
if (code == KeyEvent.VK_DOWN) {
if (bomb.isFalling == false)
bomb.isFalling = true;
bomb.centerX = boat.centerX;
bomb.centerY = boat.centerY;
}
}
}
);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (boat == null) {
width = getWidth();
height = getHeight();
boat = new Boat();
sub = new Submarine();
bomb = new Bomb();
}
if (hasFocus())
g.setColor(Color.CYAN);
else {
g.setColor(Color.RED);
g.drawString("CLICK TO ACTIVATE", 20, 30);
g.setColor(Color.GRAY);
}
g.drawRect(0,0,width-1,height-1);
g.drawRect(1,1,width-3,height-3);
g.drawRect(2,2,width-5,height-5);
boat.draw(g);
sub.draw(g);
bomb.draw(g);
}
private class Boat {
int centerX, centerY;
Boat() {
centerX = width/2;
centerY = 80;
}
void updateForNewFrame() {
if (centerX < 0)
centerX = 0;
else
if (centerX > width)
centerX = width;
}
void draw(Graphics g) {
g.setColor(Color.blue);
g.fillRoundRect(centerX - 40, centerY - 20, 80, 40, 20, 20);
}
}
private class Bomb {
int centerX, centerY;
boolean isFalling;
Bomb() {
isFalling = false;
}
void updateForNewFrame() {
if (isFalling) {
if (centerY > height) {
isFalling = false;
}
else
if (Math.abs(centerX - sub.centerX) <= 36 && Math.abs(centerY - sub.centerY) <= 21) {
sub.isExploding = true;
sub.explosionFrameNumber = 1;
isFalling = false; // Bomba reapare in barca
}
else {
centerY += 10;
}
}
}
void draw(Graphics g) {
if ( !isFalling ) {
centerX = boat.centerX;
centerY = boat.centerY + 23;
}
g.setColor(Color.RED);
g.fillOval(centerX - 8, centerY - 8, 16, 16);
}
}
private class Submarine {
int centerX, centerY;
boolean isMovingLeft;
boolean isExploding;
int explosionFrameNumber;
Submarine() {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
void updateForNewFrame() {
if (isExploding) {
explosionFrameNumber++;
if (explosionFrameNumber == 30) {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
}
else {
if (Math.random() < 0.04) {
isMovingLeft = ! isMovingLeft;
}
if (isMovingLeft) {
centerX -= 5;
if (centerX <= 0) {
centerX = 0;
isMovingLeft = false;
}
}
else {
centerX += 5;
if (centerX > width) {
centerX = width;
isMovingLeft = true;
}
}
}
}
void draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillOval(centerX - 30, centerY - 15, 60, 30);
if (isExploding) {
g.setColor(Color.YELLOW);
g.fillOval(centerX - 4*explosionFrameNumber, centerY - 2*explosionFrameNumber,
8*explosionFrameNumber, 4*explosionFrameNumber);
g.setColor(Color.RED);
g.fillOval(centerX - 2*explosionFrameNumber, centerY - explosionFrameNumber/2,
4*explosionFrameNumber, explosionFrameNumber);
}
}
}
}
The SubKiller class, where the main method is located.
import javax.swing.JFrame;
public class SubKiller {
public static void main(String[] args) {
JFrame window = new JFrame("Sub Killer Game");
SubKillerPanel content = new SubKillerPanel();
window.setContentPane(content);
window.setSize(700, 700);
window.setLocation(0,0);
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
window.setResizable(false);
window.setVisible(true);
}
}
You only have a single Bomb being tracked by the graphics at any time. You should build a collection of Bombs and instantiate a new one whenever the down key is pressed, then iterate through all the collection of Bombs and draw them as needed.
So, instead of private Bomb bomb;
You would have private List<Bomb> bombs;
Afterwards, anywhere you update the single bomb you can use a for loop to go through the list of bombs and have them all update, and then if they are no longer being drawn, remove them from the list.
This snake game code. I want to add the system score in this game. So that each time the snake eating his score would be increased. But if the snake does not get food score will not increase.
How do I go about displaying the current score?
this is :
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener {
private final int WIDTH = 300;
private final int HEIGHT = 300;
private final int DOT_SIZE = 10;
private final int ALL_DOTS = 900;
private final int RAND_POS = 29;
private final int DELAY = 140;
private int x[] = new int[ALL_DOTS];
private int y[] = new int[ALL_DOTS];
private int dots;
private int apple_x;
private int apple_y;
private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private boolean inGame = true;
private Timer timer;
private Image ball;
private Image apple;
private Image head;
public Board() {
addKeyListener(new TAdapter());
setBackground(Color.black);
ImageIcon iid = new ImageIcon(this.getClass().getResource("dot.png"));
ball = iid.getImage();
ImageIcon iia = new ImageIcon(this.getClass().getResource("apple.png"));
apple = iia.getImage();
ImageIcon iih = new ImageIcon(this.getClass().getResource("head.png"));
head = iih.getImage();
setFocusable(true);
initGame();
}
public void initGame() {
dots = 3;
for (int z = 0; z < dots; z++) {
x[z] = 50 - z*10;
y[z] = 50;
}
locateApple();
timer = new Timer(DELAY, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
if (inGame) {
g.drawImage(apple, apple_x, apple_y, this);
for (int z = 0; z < dots; z++) {
if (z == 0)
g.drawImage(head, x[z], y[z], this);
else g.drawImage(ball, x[z], y[z], this);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
} else {
gameOver(g);
}
}
public void gameOver(Graphics g) {
String msg = "Game Over";
Font small = new Font("Helvetica", Font.BOLD, 14);
FontMetrics metr = this.getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2,
HEIGHT / 2);
}
public void checkApple() {
if ((x[0] == apple_x) && (y[0] == apple_y)) {
dots++;
locateApple();
}
}
public void move() {
for (int z = dots; z > 0; z--) {
x[z] = x[(z - 1)];
y[z] = y[(z - 1)];
}
if (left) {
x[0] -= DOT_SIZE;
}
if (right) {
x[0] += DOT_SIZE;
}
if (up) {
y[0] -= DOT_SIZE;
}
if (down) {
y[0] += DOT_SIZE;
}
}
public void checkCollision() {
for (int z = dots; z > 0; z--) {
if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
inGame = false;
}
}
if (y[0] > HEIGHT) {
inGame = false;
}
if (y[0] < 0) {
inGame = false;
}
if (x[0] > WIDTH) {
inGame = false;
}
if (x[0] < 0) {
inGame = false;
}
}
public void locateApple() {
int r = (int) (Math.random() * RAND_POS);
apple_x = ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
apple_y = ((r * DOT_SIZE));
}
public void actionPerformed(ActionEvent e) {
if (inGame) {
checkApple();
checkCollision();
move();
}
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!right)) {
left = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_RIGHT) && (!left)) {
right = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_UP) && (!down)) {
up = true;
right = false;
left = false;
}
if ((key == KeyEvent.VK_DOWN) && (!up)) {
down = true;
right = false;
left = false;
}
}
}
You need two things:
1) Code to add the score - you should check after the move to see whether the snake's head is at the same coordinates as the apple, if so add to the score.
2) Create a JLabel to store the value of the player's score. On each timer invoked ActionPerformed, update the text of this JLabel. You won't need to worry about Multi-threading, the action event handlers invoked by the Timer are handled in a separate thread.