Snake is an older classic video game. It was first created in late 70s. Later it was brought to PCs. In this game the player controls a snake. The objective is to eat as many apples as possible. Each time the snake eats an apple, its body grows. The snake must avoid the walls and its own body. This game is sometimes called Nibbles.
How to Make Snake Game In Swing,Make Snake Game In Swing,Snake Game In Swing,Game In Swing,

Development

The size of each of the joints of a snake is 10px. The snake is controlled with the cursor keys. Initially, the snake has three joints. If the game is finished, the "Game Over" message is displayed in the middle of the board.

Board.java

package com.blogspot.geekonjava;

import java.awt.Color;
import java.awt.Dimension;
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 B_WIDTH = 300;
    private final int B_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 final int x[] = new int[ALL_DOTS];
    private final int y[] = new int[ALL_DOTS];

    private int dots;
    private int apple_x;
    private int apple_y;

    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 ball;
    private Image apple;
    private Image head;

    public Board() {

        addKeyListener(new TAdapter());
        setBackground(Color.black);
        setFocusable(true);

        setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
        loadImages();
        initGame();
    }

    private void loadImages() {

        ImageIcon iid = new ImageIcon("dot.png");
        ball = iid.getImage();

        ImageIcon iia = new ImageIcon("apple.png");
        apple = iia.getImage();

        ImageIcon iih = new ImageIcon("head.png");
        head = iih.getImage();
    }

    private 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();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        doDrawing(g);
    }
    
    private void doDrawing(Graphics 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();

        } else {

            gameOver(g);
        }        
    }

    private void gameOver(Graphics g) {
        
        String msg = "Game Over";
        Font small = new Font("Helvetica", Font.BOLD, 14);
        FontMetrics metr = getFontMetrics(small);

        g.setColor(Color.white);
        g.setFont(small);
        g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2, B_HEIGHT / 2);
    }

    private void checkApple() {

        if ((x[0] == apple_x) && (y[0] == apple_y)) {

            dots++;
            locateApple();
        }
    }

    private void move() {

        for (int z = dots; z > 0; z--) {
            x[z] = x[(z - 1)];
            y[z] = y[(z - 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;
        }
    }

    private 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] >= B_HEIGHT) {
            inGame = false;
        }

        if (y[0] < 0) {
            inGame = false;
        }

        if (x[0] >= B_WIDTH) {
            inGame = false;
        }

        if (x[0] < 0) {
            inGame = false;
        }
        
        if(!inGame) {
            timer.stop();
        }
    }

    private 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));
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if (inGame) {

            checkApple();
            checkCollision();
            move();
        }

        repaint();
    }

    private class TAdapter extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();

            if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) {
                leftDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) {
                rightDirection = true;
                upDirection = false;
                downDirection = false;
            }

            if ((key == KeyEvent.VK_UP) && (!downDirection)) {
                upDirection = true;
                rightDirection = false;
                leftDirection = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!upDirection)) {
                downDirection = true;
                rightDirection = false;
                leftDirection = false;
            }
        }
    }
}
First we will define the constants used in our game.
private final int B_WIDTH = 300;
private final int B_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;
The B_WIDTH and B_HEIGHT constants determine the size of the board. The DOT_SIZE is the size of the apple and the dot of the snake. The ALL_DOTS constant defines the maximum number of possible dots on the board (900 = (300*300)/(10*10)). The RAND_POS constant is used to calculate a random position for an apple. The DELAY constant determines the speed of the game.
private final int x[] = new int[ALL_DOTS];
private final int y[] = new int[ALL_DOTS];
These two arrays store the x and y coordinates of all joints of a snake.
private void loadImages() {

    ImageIcon iid = new ImageIcon("dot.png");
    ball = iid.getImage();

    ImageIcon iia = new ImageIcon("apple.png");
    apple = iia.getImage();

    ImageIcon iih = new ImageIcon("head.png");
    head = iih.getImage();
}
In the loadImages() method we get the images for the game. The ImageIcon class is used for displaying PNG images.
private 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();
}
In the initGame() method we create the snake, randomly locate an apple on the board, and start the timer.
private void checkApple() {

    if ((x[0] == apple_x) && (y[0] == apple_y)) {

        dots++;
        locateApple();
    }
}
If the apple collides with the head, we increase the number of joints of the snake. We call the locateApple() method which randomly positions a new apple object.

In the move() method we have the key algorithm of the game. To understand it, look at how the snake is moving. We control the head of the snake. We can change its direction with the cursor keys. The rest of the joints move one position up the chain. The second joint moves where the first was, the third joint where the second was etc.
for (int z = dots; z > 0; z--) {
    x[z] = x[(z - 1)];
    y[z] = y[(z - 1)];
}
This code moves the joints up the chain.
if (leftDirection) {
    x[0] -= DOT_SIZE;
}
This line moves the head to the left.
In the checkCollision() method, we determine if the snake has hit itself or one of the walls.
for (int z = dots; z > 0; z--) {

    if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
        inGame = false;
    }
}
If the snake hits one of its joints with its head the game is over.
if (y[0] >= B_HEIGHT) {
    inGame = false;
}
The game is finished if the snake hits the bottom of the board.


Snake.java

package com.blogspot.geekonjava;

import java.awt.EventQueue;
import javax.swing.JFrame;


public class Snake extends JFrame {

    public Snake() {

        add(new Board());
        
        setResizable(false);
        pack();
        
        setTitle("Snake");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    

    public static void main(String[] args) {
        
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {                
                JFrame ex = new Snake();
                ex.setVisible(true);                
            }
        });
    }
}
This is the main class.
setResizable(false);
pack();
The setResizable() method affects the insets of the JFrame container on some platforms. Therefore, it is important to call it before the pack() method. Otherwise, the collision of the snake's head with the right and bottom borders might not work correctly.
2

View comments

  1. Hi I'm having trouble loading the images it seems like it can't detect the images T^T Help I have already copied the .png images in the class package but it doesn't work

    ReplyDelete
    Replies
    1. Are you put that images in any folder or in root folder ?

      Delete


  1.  

    0

    Add a comment

  2. Easy Steps to Add 301 Redirects to WordPress » Tell Me How - A Place for Technology Geekier: Before we try to learn how to add 301 redirects to WordPress, we need to understand what they really are. If you run your own website, it is a must to understand the ‘when’ and ‘how’ of using these. If you are ignorant on the topic, you could be losing a lot of organic traffic …
    0

    Add a comment

  3. Is Purefit Keto Beneficial For Weight Loss? » Tell Me How - A Place for Technology Geekier: The ketogenic diet is probably something that everyone interested in physical fitness might have heard about. In this diet plan, you eat lots of fat so that your body to burn even more fat. Purefit is a supplement that helps your body to do that. When our body is in a state of normal metabolism …
    0

    Add a comment

  4. The Best SEO Practices for Blogging » Tell Me How - A Place for Technology Geekier: How can SEO help your blog and vice versa? Today, we will give you some information about the best SEO Practices for Blogging.
    0

    Add a comment

  5. json2view : Some important properties and types » Tell Me How - A Place for Technology Geekier: Here we see some important properties and types of json2view library which you can use in your applications. Just dive and enjoy the tutorials and code.
    0

    Add a comment

  6. Yes You Can! How Millennials Can Actually Afford a House » Tell Me How - A Place for Technology Geekier: The consensus across the world is that Millennials can’t afford to buy houses. Sadly, this means that a lot of them have stopped trying. To be clear, Millennials can afford to buy a house in a lot of cases. They are, however, facing more barriers and challenges in homeownership than any generation has ever faced.  …
    0

    Add a comment

  7. THE BEST GADGETS FOR STUDYING OF 2020 
    0

    Add a comment

  8. However, along with this news, how are JDK builds available? Will they be free or paid? Before answering this, it's important to understand what a "valid" JDK for distribution actually means. In practical terms, there is only one set of source code for the JDK. 

    JDK Alternatives for Production
    JDK Alternatives for Production



    The source code is hosted here. Anyone can pick up this source code, produce a build, and post it to a URL. However, there is a separate certification process that must be used to ensure that construction is valid. Certification is performed by the Java Community Process (JCP), which provides a Technology Compatibility Kit (TCK). 
    If an organization produces an OpenJDK build that complies with the entirely TCK, this build may be described as "compatible with Java SE".
    Note that the build cannot be called "Java SE" without the vendor obtaining a commercial license from Oracle. For example, AdoptOpenJDK builds that pass the TCK are not "Java SE," but "Java SE compliant" or "Java SE compliant." Also, note that certification is currently on a trust basis — results are not sent to JCP/Oracle for verification and cannot be made public. In short, the OpenJDK + Vendor process transforms a source base into several different builds.

    Figure 1: OpenJDK source code transformed into builds (per Vendor)


    Without further ado, check out the following JDKs that are ready to download: Alternatives of Premium JDK





    0

    Add a comment

  9. Animated Recycler View is a library that allows you to animate a recycler view in your project like Google does it in its Google Play Store. Only the first visible items are animated there and you will see no animation when the recycler view scrolls up.
    Animated Recycler View - Transition Page Recycler with layout animations
    Animated Recycler View – Transition Page Recycler with layout animations

    Reasons to use it

    This library solves several problems:
    1. It works stably fast and without jerks.
    2. It doesn’t need to utilize the adapter to animate items when they appear for the first time.

    Why Animated Recycler View is special for you?

    While working on a project, most of time we need animation similar to the one used in the Google Play Store but didn’t find any appropriate library on Internet/ Github/ StackOverflow that could help us with this task. 
    Source: How to Transition Page Recycler using Animated Recycler View? 
    0

    Add a comment



  10. There are so many ways to make mobile apps ranging from direct platform specific development (using Java and Kotlin for Android, and ObjC and Swift for iOS), there’s React Native from Facebook, Electrode Native from Walmart, the Ionic framework, Unity for certain types of apps, and the flutter.io framework which was just released by Google.



    Ever wondered how these libraries and frameworks affect the size of your app? Let’s analyze some apk files for apps written in some of these ways. The apps are very basic, containing just a title at the top and a text at the center of the screen.

    This will show, for a bare minimum app what these frameworks need to package along with the apk for it to be able to run.

    • For this test I created four different versions of the app, one in each of JavaKotlinReact Nativeand Flutter. (Android API 27)
    • The apks were then published for release type using Android Studio for Java and Kotlin and using the cli for React Native and Flutter.
    • Default proguard configuration was used.
    • The apks were analyzed using the Analyze APK feature in Android Studio.
    Source: Which Language is Good for Android by Analyze APK sizes?
    0

    Add a comment

Contributors
Contributors
Popular Posts
Popular Posts
Archive
Labels
Labels
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.