GUI programming --- Snake game development

Posted by MikeUK on Tue, 08 Feb 2022 00:00:51 +0100

① First knowledge theory
Frame: the time slice is small enough = "is the animation, 1 second 30 frames. Connect is animation, open is static picture!
Keyboard monitor
Timer timer

② Game development ideas

(define data, draw a panel, and listen for events (keyboard / event))

1. First of all, a game main startup class, StartGame class, in which a JFrame window and its size and position settings are placed, and the closing settings are set. Here, the window size is not changed to prevent stretching from deforming the game icon. The relevant specific operations are carried out in the corresponding classes!

2. The normal game interface should be on the panel! First of all, the paintpanel method in the game is defined by the paintbrush! First, draw the static panel and set the panel color to white.

3. Then put game Put the picture material into the static dictionary, put it under the game development package, define a Data class, get the address where the game pictures are stored, turn them into icons, and then draw the head advertisement bar and rectangular (default black) game interface on the petals.

4. Draw a static snake and define the data structure of the snake in the GamePanel class!

int length; => Snake length

int[] snakeX=new int[600]; => The x coordinate of the snake's position is 25 * 25

int[] snakeY=new int[500]; => The y coordinate of the snake's position is 25 * 25

String fx; => Initial direction

Then write initialization method init() method to initialize the length, position and initial direction of the static snake, then call the init() method in the constructor, then draw the little snake into the panel. (to determine the direction of the head!), The body is drawn in a for loop.

5. Current state of the game inStart: start / stop, space bar control! The initial setting is to stop false. After judging the status, draw the prompt text on the panel!

6. The space bar controls the start and stop of the game! Set keyboard monitoring! Directly implement the KeyListener interface in the GamePanel class! Press the spacebar – > to reverse the status, redraw repaint(), and then set the focus event and add keyboard monitoring in the init() function.

7. Snake move, Timer! Just implement the ActionListener interface in the GamePanel class. Start the Timer at the beginning of the game! Then write out the processing of the position coordinates of the snake's movement, how the head and body coordinates change when it moves up, down, left and right, and finally repaint() redraws the page. So the little snake can move by itself. But we need to monitor the up, down, left and right keys through the keyboard to control the movement of the snake! Body movement is the same. We just need to judge the moving direction and find the position coordinates of the head!

8. When the snake grows up ~, it defines the coordinates of the food and initializes it in init()

int foodX;

int foodY;

Random random=new Random();

Eating food means that the head coordinates coincide with the food coordinates. The snake length is + 1. Random food is generated again. After eating food, draw the body!

9. Define the failure status. The default is no failure. If a text prompt needs to appear on the failure panel, just draw it on the panel. The space bar may start / stop the game or restart the game after failure, so pressing the space bar will judge whether to start / stop or restart the game according to the charging isFail when the game fails! If the game starts and does not fail, you need to add the failure judgment after the direction: if the head coordinate coincides with any coordinate of your body, the game fails, isfail=true! At this time, the prompt of game failure will appear. Pressing the space bar is to reinitialize and start the game, rather than the ordinary pause and start.

10. Score, define data, draw drawing board, monitor: eat food score + 10

11. Implementation code:

package com.xiao.lesson07_game;import javax.swing.*;// Main startup class of the game
public class StartGame {

public static void main(String[] args) {
    JFrame frame = new JFrame("Greedy snake");

    //The normal game interface should be on the panel
    frame.add(new GamePanel());
    
    frame.setBounds(10,10,900,720);
    frame.setResizable(false);//Immutable size
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setVisible(true);
}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

package com.xiao.lesson07_game;import javax.swing.*;import java.net.URL;// Data center
public class Data {

//Relative path "tx.jpg"
//Absolute path: / equivalent to the current project
//Head + body + food
public static URL headerURL=Data.class.getResource("statics/header.png");
public static ImageIcon header=new ImageIcon(headerURL);
public static URL bodyURL=Data.class.getResource("statics/body.png");
public static ImageIcon body=new ImageIcon(bodyURL);
public static URL foodURL=Data.class.getResource("statics/food.png");
public static ImageIcon food=new ImageIcon(foodURL);

//Up, down, left and right
public static URL upURL=Data.class.getResource("statics/up.png");
public static URL downURL=Data.class.getResource("statics/down.png");
public static URL leftURL=Data.class.getResource("statics/left.png");
public static URL rightURL=Data.class.getResource("statics/right.png");
public static ImageIcon up=new ImageIcon(upURL);
public static ImageIcon down=new ImageIcon(downURL);
public static ImageIcon left=new ImageIcon(leftURL);
public static ImageIcon right=new ImageIcon(rightURL);}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

package com.xiao.lesson07_game;import javax.swing.;import java.awt.;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.util.Random;// Game panel
public class GamePanel extends JPanel implements KeyListener, ActionListener {

//Define the data structure of the snake
int length;  //length
int[] snakeX=new int[600]; //x coordinate 25 * 25
int[] snakeY=new int[500]; //y coordinate 25 * 25
String fx; //Initial direction

//Food coordinates (random!)
int foodX;  //Normal food
int foodY;
Random random=new Random();//random

int score;  //achievement

boolean isStart=false;// Current state of the game: start / stop, default stop

boolean isFail=false;  //Game failure status

//Timer in milliseconds
Timer timer=new Timer(100,this); //Once every 100ms

//constructor 
public GamePanel() {
    init();
    //Get focus and keyboard monitoring
    this.setFocusable(true);  //Get focus event
    this.addKeyListener(this);  //Get keyboard listener
    timer.start();//The timer starts as soon as the game starts

    //The food coordinates have to be in the game interface for the snake to eat! foodX=25+25*random.nextInt(34);
    foodY=75+25*random.nextInt(24);

    score=0;
}

//Snake initialization method
public void init(){
    length=3;
    snakeX[0]=100;  snakeY[0]=100;  //Head coordinates
    snakeX[1]=75;  snakeY[1]=100;  //First body coordinates
    snakeX[2]=50;  snakeY[2]=100;  //Second body coordinate fx="R"// Initial direction right}

//Drawing panel, everything in the game is painted with this brush!
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g); //Clear screen
    //Draw static panels
    this.setBackground(Color.WHITE);
    Data.header.paintIcon(this, g, 25, 11);//Draw a banner on your head
    g.fillRect(25, 75, 850, 600);  //Draw rectangle = game interface

    //Draw integral
    g.setColor(Color.WHITE);
    g.setFont(new Font("Microsoft YaHei ",Font.BOLD,18));
    g.drawString("Length:"+length,775,30);
    g.drawString("fraction:"+score,775,50);
    //Draw food
    Data.food.paintIcon(this,g,foodX,foodY);
    //If you draw the snake, you have to judge the initial direction! if (fx.equals("R")) {
        Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//Snakehead initialization right} else if (fx.equals("L")){
        Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);//Snakehead initialization right} else if (fx.equals("U")){
        Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);//Snakehead initialization right} else if (fx.equals("D")){
        Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);//Snakehead initialization right}
    for (int i = 1; i < length; i++) {
        Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);//Body}

    //Game status
    if(isStart==false){
        g.setColor(Color.WHITE);//Set brush color
        g.setFont(new Font("Microsoft YaHei ",Font.BOLD,40));//Set font
        g.drawString("Press the space bar to start the game!",250,380);  //Write game tips}

    if(isFail){
        g.setColor(Color.WHITE);//Set brush color
        g.setFont(new Font("Microsoft YaHei ",Font.BOLD,40));//Set font
        g.drawString("Score:"+score,230,330);
        score=0;
        g.setColor(Color.RED);//Set brush color
        g.drawString("Failed, press the space bar to start again!",230,380);  //Write game tips}
}

//Keyboard monitoring events: press the keyboard to control the start and stop of the game
@Override
public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();  //Which keyboard key is obtained

    if(keyCode==KeyEvent.VK_SPACE){
        if(isFail){
            //Restart isFail=false;
            init();
        }else{
        isStart=!isStart;  //Reverse}
        repaint();
    }

    //The little snake moves up, down, left and right
    if(keyCode==KeyEvent.VK_UP){
        fx="U";
    }else if(keyCode==KeyEvent.VK_DOWN){
        fx="D";
    }else if(keyCode==KeyEvent.VK_LEFT){
        fx="L";
    }else if(keyCode==KeyEvent.VK_RIGHT){
        fx="R";
    }
}
@Override
public void keyReleased(KeyEvent e) { }
@Override
public void keyTyped(KeyEvent e) { }


//Event monitoring -- refresh through fixed events, 1s=10 times, Timer
@Override
public void actionPerformed(ActionEvent e) {
    //If the game is at the beginning, let the snake move
    if(isStart && isFail==false) {
        //Eat food, coordinate coincidence if ((snake [0] = = foodx & & Snake [0] = = Foody)){
            length++;  //The little snake is long! score+=10;
            //Food is randomly generated again!
            foodX = 25 + 25 * random.nextInt(34);
            foodY = 75 + 25 * random.nextInt(24);
            }

        //Body movement does not change! All the same for (int i = length - 1; I > 0; I --){
            //Move one section forward and the next section becomes the position of the previous section
            snakeX[i] = snakeX[i - 1];
            snakeY[i] = snakeY[i - 1];
        }
        //Trend if (fx.equals("R"){
            //Shift right
            snakeX[0] = snakeX[0] + 25;
            if (snakeX[0] > 850) {
                snakeX[0] = 25;
            }  //Boundary judgment} else if (fx.equals("L")){
            //Shift left
            snakeX[0] = snakeX[0] - 25;
            if (snakeX[0] < 25) {
                snakeX[0] = 850;
            }
        } else if (fx.equals("U")) {
            //Move up
            snakeY[0] = snakeY[0] - 25;
            if (snakeY[0] < 75) {
                snakeY[0] = 650;
            }
        } else if (fx.equals("D")) {
            //Move down
            snakeY[0] = snakeY[0] + 25;
            if (snakeY[0] > 650) {
                snakeY[0] = 75;
            }
        }
        //Failure judgment: hit yourself for (int i = 1; I < length; I + +){
            if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){
                isFail=true;
            }
        }
        repaint();//Redraw page}
    timer.start();

13. Packaging and publishing

Click Project Structure – > artifacts – > "+" sign – > select JAR – > from modules with dependencies, and select the main method function. For example, you can start the class at www.cungun.com and apply.

Select build – > build artifacts – > build, and wait to see the artifacts directory under the out directory of the project, which is the generated jar package, which can be sent to friends to play

Open from the command line: Java - jar GUI - study Jar, you can start the snake game!

14. Optimization (not implemented!)

Level: the faster you get to the back! Set the timer delay according to the level

Wall impact judgment

The little snake can't turn back

Food form, fraction or length increase differently

Interface optimization

Game online (network programming)

Topics: Javascript css3 Vue.js html css