Snake Game using Java Swing and Java AWT in Java

Hi, Today we are learning to build a simple snake game in java using Java-Swing and Java AWT. Java-Swing is a lightweight and cross-platform toolkit used to provide GUI to java programs.

Java AWT is an API that is used for providing GUI to Java applications. But Java AWT is platform-dependent and heavyweight.

In this project, we are using swing for the GUI of the Game, and AWT is used for some predefined methods which are available in it.

Let’s discuss the code and logic’s to build this Game.

So to build this game we are programing 3 java classes that are:-

Snake Game    Main Class

SnakeFrame    For creating Java Swing Application window

SnakePanel     This class is used for updating the length of the snake and randomly painting food on the screen and also moving the snake according to the keyboard inputs.

There is another class inside the Snake Panel class MyKey Class that class is used to handle keyboard inputs.

First, we are programing the Snake Frame class.

import javax.swing.JFrame;

public class  SnakeFrame extends JFrame {
    SnakeFrame(){
        this.add(new SankePanel());
        this.setTitle("Snake");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.pack();
        this.setVisible(true);
        this.setLocationRelativeTo(null);
        

    }
}

In this class, we are creating a JFrame and setting its title, and also creating a Snake panel object.

Now we are coding for the Jpanel in this class we creating some functions to perform different functionalities like move, start game, etc.

First, we are creating a constructor of the panel class and creating the Game_start function.

SankePanel(){
    this.setPreferredSize(new Dimension(S_Width,S_Height));
    this.setBackground(Color.gray);
    this.setFocusable(true);
    this.addKeyListener(new MyKey());
    random = new Random();
    Game_start();
}
public void Game_start() {
    newfoodPosition();
    game_flag=true;
    timer=new Timer(DELAY,this);
    timer.start();
}

 

Now we will code for the draw function and paint function.

public void paintComponent(Graphics graphic) {
        super.paintComponent(graphic);
        draw(graphic);
    }
    public void draw(Graphics graphic) {
        if(game_flag){
            graphic.setColor(Color.yellow);
            graphic.fillOval(foodX, foodY,Game_unit_size,Game_unit_size);
            for(int i=0;i<bodylength;i++){
                if(i==0){
                    graphic.setColor(Color.green);
                    graphic.fillRect(x_snake[i],y_snake[i],Game_unit_size,Game_unit_size);
                }
                else{
                    graphic.setColor(new Color(50,180,0));
                    graphic.fillRect(x_snake[i],y_snake[i],Game_unit_size,Game_unit_size);
                }
            }
           graphic.setColor(Color.blue);
           graphic.setFont(new Font("Ink Free",Font.BOLD,40));
           FontMetrics font_me=getFontMetrics(graphic.getFont());
           graphic.drawString("Score:"+foodEAten,(S_Width-font_me.stringWidth("Score:"+foodEAten))/2,graphic.getFont().getSize());

        }
        else{
            gameOver(graphic);
        }
    }

 

Now we are creating a MyKey class for keyboard inputs.

public class MyKey extends KeyAdapter{
    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                if(dir!='R'){
                    dir='L';
                }
                break;
            case KeyEvent.VK_UP:
                if (dir != 'D') {
                    dir = 'U';
                }
                break;
            case KeyEvent.VK_RIGHT:
                if (dir != 'L') {
                    dir = 'R';
                }
                break;
            case KeyEvent.VK_DOWN:
                if (dir != 'U') {
                    dir = 'D';
                }
                break;
            case KeyEvent.VK_R:
            if(!game_flag){
                foodEAten=0;
                bodylength=2;
                dir='R';
               Arrays.fill(x_snake,0);
               Arrays.fill(y_snake,0);
                Game_start();
            }
            break;
        }            
    }
}

 

This class extends the KeyAdapter Class of the Java AWT  event package. Now we have to code for the food of the snake, movement of the snake, and also for game over.

 public void newfoodPosition() {// for displaying food at a random position on the screen
        foodX=random.nextInt((int)(S_Width/Game_unit_size))*Game_unit_size;
        foodY=random.nextInt((int)(S_Height/Game_unit_size))*Game_unit_size;
    }
    public void food_EatenOrNot() {// for checking the food has been eaten by snake or not
        if((x_snake[0]==foodX)&&(y_snake[0]==foodY)){
            bodylength++;
            foodEAten++;
            newfoodPosition();
        }
    }
    public void checkHit() {
// for checking if by mistake snake bite itself and if it collides with walls
        for (int i=bodylength;i>0;i--)
            {if((x_snake[0]==x_snake[i])&&(y_snake[0]==y_snake[i]))
                {game_flag=false;}}
        if(x_snake[0]<0)
            {game_flag=false;}
        if(x_snake[0]>S_Width)
           { game_flag=false;}
        if (y_snake[0] < 0) 
        {    game_flag = false;}
        if (y_snake[0] > S_Height) 
        {    game_flag = false;}
        if(!game_flag)
          {  timer.stop();}
    }
    public void gameOver(Graphics graphic) {// When ever game is over this function will be called.
        graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 40));
        FontMetrics font_me = getFontMetrics(graphic.getFont());
        graphic.drawString("Score:" + foodEAten, (S_Width - font_me.stringWidth("Score:" + foodEAten)) / 2,
                graphic.getFont().getSize());
        graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 75));
        FontMetrics font_me2 = getFontMetrics(graphic.getFont());
        graphic.drawString("Game Over", (S_Width - font_me2.stringWidth("Game Over")) / 2,
                S_Height/2);
                graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 40));
        FontMetrics font_me3 = getFontMetrics(graphic.getFont());
        graphic.drawString("Press R to Replay", (S_Width - font_me3.stringWidth("Press R to Replay")) / 2, S_Height / 2-150);

    }

 

Now finally we require a function that calls check functions, again and again, to check the movements of the snake for we have extended ActionListner class in GamePlane class.

  
@Override
public void actionPerformed(ActionEvent arg0) {
    if (game_flag) {
        move();
        food_EatenOrNot();
        checkHit();
    }
    repaint();
}

Woohoo, we finally understand the logic behind this game so let’s copy the complete codes of each class and play our own build snake game.

SnakeGame.java(Main Class)

public class SnakeGame {
    public static void main(String[] args) throws Exception {
      new SnakeFrame();
      
    }
}

SnakeFrame.java(Frame class)

import javax.swing.JFrame;

public class  SnakeFrame extends JFrame {
    SnakeFrame(){
        this.add(new SankePanel());
        this.setTitle("Snake");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.pack();
        this.setVisible(true);
        this.setLocationRelativeTo(null);
        

    }
}

SnakePanel.java(Panel Class)

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import java.util.Random;
public class SankePanel extends JPanel implements ActionListener{
    static final int S_Width=1200;
    static final int S_Height=600;
    static final int Game_unit_size=50;
    Timer timer;
    Random random;
    int foodEAten;
    int foodX;
    int foodY;
    int bodylength = 2;
    boolean game_flag = false;
    char dir = 'R';
    static final int DELAY = 160;
    static final int G_Size=(S_Width*S_Height)/(Game_unit_size*Game_unit_size);
    final int x_snake[]=new int[G_Size];
    final int y_snake[]=new int[G_Size];
    SankePanel(){
        this.setPreferredSize(new Dimension(S_Width,S_Height));
        this.setBackground(Color.gray);
        this.setFocusable(true);
        this.addKeyListener(new MyKey());
        random = new Random();
        Game_start();
    }
    public void Game_start() {
        newfoodPosition();
        game_flag=true;
        timer=new Timer(DELAY,this);
        timer.start();
    }
    public void paintComponent(Graphics graphic) {
        super.paintComponent(graphic);
        draw(graphic);
    }
    public void draw(Graphics graphic) {
        if(game_flag){
            graphic.setColor(Color.yellow);
            graphic.fillOval(foodX, foodY,Game_unit_size,Game_unit_size);
            for(int i=0;i<bodylength;i++){
                if(i==0){
                    graphic.setColor(Color.green);
                    graphic.fillRect(x_snake[i],y_snake[i],Game_unit_size,Game_unit_size);
                }
                else{
                    graphic.setColor(new Color(50,180,0));
                    graphic.fillRect(x_snake[i],y_snake[i],Game_unit_size,Game_unit_size);
                }
            }
           graphic.setColor(Color.blue);
           graphic.setFont(new Font("Ink Free",Font.BOLD,40));
           FontMetrics font_me=getFontMetrics(graphic.getFont());
           graphic.drawString("Score:"+foodEAten,(S_Width-font_me.stringWidth("Score:"+foodEAten))/2,graphic.getFont().getSize());

        }
        else{
            gameOver(graphic);
        }
    }
    public void move() {
        for(int i=bodylength;i>0;i--){
            x_snake[i]=x_snake[i-1];
            y_snake[i]=y_snake[i-1];

        }
        switch (dir) {
            case 'U':
            y_snake[0]=y_snake[0]-Game_unit_size;
                break;
            case 'L':
                x_snake[0] = x_snake[0] - Game_unit_size;
                break;
            case 'D':
                y_snake[0] = y_snake[0] + Game_unit_size;
                break;
            case 'R':
                x_snake[0] = x_snake[0] + Game_unit_size;
                break;
        }
    }
    public void newfoodPosition() {// for displaying food at a random position on the screen
        foodX=random.nextInt((int)(S_Width/Game_unit_size))*Game_unit_size;
        foodY=random.nextInt((int)(S_Height/Game_unit_size))*Game_unit_size;
    }
    public void food_EatenOrNot() {// for checking the food has been eaten by snake or not
        if((x_snake[0]==foodX)&&(y_snake[0]==foodY)){
            bodylength++;
            foodEAten++;
            newfoodPosition();
        }
    }
    public void checkHit() {
// for checking if by mistake snake bite itself and if it collides with walls
        for (int i=bodylength;i>0;i--)
            {if((x_snake[0]==x_snake[i])&&(y_snake[0]==y_snake[i]))
                {game_flag=false;}}
        if(x_snake[0]<0)
            {game_flag=false;}
        if(x_snake[0]>S_Width)
           { game_flag=false;}
        if (y_snake[0] < 0) 
        {    game_flag = false;}
        if (y_snake[0] > S_Height) 
        {    game_flag = false;}
        if(!game_flag)
          {  timer.stop();}
    }
    public void gameOver(Graphics graphic) {// When ever game is over this function will be called.
        graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 40));
        FontMetrics font_me = getFontMetrics(graphic.getFont());
        graphic.drawString("Score:" + foodEAten, (S_Width - font_me.stringWidth("Score:" + foodEAten)) / 2,
                graphic.getFont().getSize());
        graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 75));
        FontMetrics font_me2 = getFontMetrics(graphic.getFont());
        graphic.drawString("Game Over", (S_Width - font_me2.stringWidth("Game Over")) / 2,
                S_Height/2);
                graphic.setColor(Color.red);
        graphic.setFont(new Font("Ink Free", Font.BOLD, 40));
        FontMetrics font_me3 = getFontMetrics(graphic.getFont());
        graphic.drawString("Press R to Replay", (S_Width - font_me3.stringWidth("Press R to Replay")) / 2, S_Height / 2-150);

    }
    public class MyKey extends KeyAdapter{
        @Override
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    if(dir!='R'){
                        dir='L';
                    }
                    break;
                case KeyEvent.VK_UP:
                    if (dir != 'D') {
                        dir = 'U';
                    }
                    break;
                case KeyEvent.VK_RIGHT:
                    if (dir != 'L') {
                        dir = 'R';
                    }
                    break;
                case KeyEvent.VK_DOWN:
                    if (dir != 'U') {
                        dir = 'D';
                    }
                    break;
                case KeyEvent.VK_R:
                if(!game_flag){
                    foodEAten=0;
                    bodylength=2;
                    dir='R';
                   Arrays.fill(x_snake,0);
                   Arrays.fill(y_snake,0);
                    Game_start();
                }
                break;
            }            
        }
    }
    
    @Override
    public void actionPerformed(ActionEvent arg0) {
        if (game_flag) {
            move();
            food_EatenOrNot();
            checkHit();
        }
        repaint();
    }
    
}

 Output

In the image below, you can see the output result of our code.

snakeGame

Try this by yourself.

Thank you for reading this blog.

Leave a Reply

Your email address will not be published.