Practical development of Java games -- greedy Snake games
1. Direction class
Direction: used to store up, down, left and right keys.
package com.games; /* *Enumeration: just a few fixed constants */ public enum Direction{ UP,DOWN,LEFT,RIGHT }
2. Snake class
Snake, Snake: a snake has multiple nodes. Use LinkedList to collect storage nodes
Initialize the snake body. The snake birthplace has 6 nodes
package com.games; import java.util.LinkedList; /** *Snake Class represents snake * A snake has multiple nodes. Use the LinkedList set to store Node nodes * The place where the snake was born has six nodes */ public class Snake { //Snake body private LinkedList<Node> body; //The direction of motion of the snake private Direction direction = Direction.LEFT; //Is the snake alive private boolean isLiving = true; //Construction method, which is executed when creating Snake object public Snake(){ //Initialize snake body initSnake(); } //Initialize snake body private void initSnake(){ //Create collection body= new LinkedList<>(); //Create 6 nodes and put them in the collection body.add(new Node(16,20)); body.add(new Node(17,20)); body.add(new Node(18,20)); body.add(new Node(19,20)); body.add(new Node(20,20)); body.add(new Node(21,20)); } //The snake moves in the direction of its head //Control Snake Movement: add a node in the movement direction of snake head, and then delete the last node of snake tail public void move(){ if(isLiving) { //Get snake head Node head = body.getFirst(); switch (direction) { case UP: //Add node on snakehead body.addFirst(new Node(head.getX(), head.getY() - 1)); break; case DOWN: body.addFirst(new Node(head.getX(), head.getY() + 1)); break; case LEFT: body.addFirst(new Node(head.getX() - 1, head.getY())); break; case RIGHT: body.addFirst(new Node(head.getX() + 1, head.getY())); break; } //Delete the last node of snaketail body.removeLast(); //Judge whether the snake hit the wall head = body.getFirst(); if(head.getX() < 0 || head.getY() < 0 || head.getX() >= 40 || head.getY() >= 40){ isLiving = false; } //Judge whether the snake touches its body for(int i = 1; i < body.size(); i++){ Node node = body.get(i); if(head.getX() == node.getX() && head.getY() == node.getY()){ isLiving = false; } } } } public LinkedList<Node> getBody() { return body; } public void setBody(LinkedList<Node> body) { this.body = body; } public Direction getDirection() { return direction; } public void setDirection(Direction direction) { this.direction = direction; } //Eat food; Add a node along the moving direction of the snake head public void eat(Node food){ //Get snake head Node head = body.getFirst(); switch (direction) { case UP: //Add node on snakehead body.addFirst(new Node(head.getX(), head.getY() - 1)); break; case DOWN: body.addFirst(new Node(head.getX(), head.getY() + 1)); break; case LEFT: body.addFirst(new Node(head.getX() - 1, head.getY())); break; case RIGHT: body.addFirst(new Node(head.getX() + 1, head.getY())); break; } } }
3. Node class
Node class: each snake is composed of several nodes, and each node has abscissa and ordinate to determine its position
package com.games; import java.util.Random; /** *Node class: each snake is composed of several nodes, and each node has abscissa and ordinate to determine its position */ public class Node { private int x; private int y; public Node(){ } public Node(int x,int y){ this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } //Randomly generated location public void random(){ //Create Random object Random r = new Random(); //Randomly generated abscissa this.x = r.nextInt(40); //Randomly generated ordinates this.y = r.nextInt(40); } }
4. MainFrame class
- realization:
- (1) initFrame() method: initialize form parameters; Set the width and height of the form, the default position of the form, the function of the close button and the immutable size of the form.
- (2) initGamePanel() method: inherit the JPanel() class, rewrite the paint() method, initialize the game board, draw the contents of the board in the paint() method, that is, empty the board, draw horizontal and vertical lines, draw snakes and food, and finally add the board to the form.
- (3) initSnake() method: initialize Snake; Create a Snake class, initialize the initial position of the Snake in the Snake class, and construct the move() method and eat() method. The move() method realizes the functions of the Snake moving along the direction of the Snake's head, judging whether the Snake hits the wall and touches its own body; The eat() method realizes that when the food coincides with the Snake head, a node will be added along the moving direction of the Snake head..
- (4) initFood() method: initialize food; Create a Node class, in which the random number is used to realize the random generation of food location.
- (5) initTimer() method: initialize the timer; Set the timing task, set the snake movement operation according to the game state and direction variable, determine the food, and judge whether the food coincides with the snake head. If so, call the eat() method and randomly generate the food again. Using the timer, call the repaint() method to update the interface in real time.
- (6) setKeyListener() method: set keyboard listening. When the keyboard is pressed, call the keyPressed(KeyEvent e) method to obtain the keyboard input, and make the snake move in the Direction according to the keyboard input.
The code is as follows:
package com.games; import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.Timer; import java.util.LinkedList; import java.util.TimerTask; public class MainFrame extends JFrame { //snake private Snake snake; //game board private JPanel jPanel; //Timer, which calls the method of snake movement within the specified time private Timer timer; //food private Node food; public MainFrame() throws HeadlessException { //Initialize form parameters initFrame(); //Initialize game board initGamePanel(); //Initialize snake initSnake(); //Initialize food initFood(); //Initialization timer initTimer(); //Set keyboard monitoring to make the snake move up, down, left and right setKeyListener(); } private void initFood(){ food = new Node(); food.random(); } private void setKeyListener(){ addKeyListener(new KeyAdapter() { //This method is called automatically when the keyboard is pressed @Override public void keyPressed(KeyEvent e) { //Each key in the keyboard has its own number switch (e.getKeyCode()){ case KeyEvent.VK_UP://Up key if(snake.getDirection() != Direction.DOWN){ //Modify the direction of motion of the snake snake.setDirection(Direction.UP); } break; case KeyEvent.VK_DOWN://Down key if(snake.getDirection() != Direction.UP){ snake.setDirection(Direction.DOWN); } break; case KeyEvent.VK_LEFT://Left key if(snake.getDirection() != Direction.RIGHT){ snake.setDirection(Direction.LEFT); } break; case KeyEvent.VK_RIGHT://Right click if(snake.getDirection() != Direction.LEFT){ snake.setDirection(Direction.RIGHT); } break; } } }); } private void initTimer(){ timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { snake.move(); //Judge whether the food coincides with the snake head Node head = snake.getBody().getFirst(); if(head.getX() == food.getX() && head.getY() == food.getY()){ snake.eat(food); food.random(); } //Redraw game board jPanel.repaint(); } }; //Perform a scheduled task every 100 milliseconds //The moving speed of the snake. If you want to change the moving speed, you can change the last parameter timer.scheduleAtFixedRate(timerTask,0,200); } private void initSnake(){ snake = new Snake(); } public void initGamePanel(){ jPanel = new JPanel(){ //Draw the contents of the chessboard public void paint(Graphics g){ //Empty chessboard g.clearRect(0,0,600,600); //Graphics g can be regarded as a brush, which provides many methods to draw some basic graphics (lines, rectangles) //Draw 40 horizontal lines for(int i = 0;i <= 40; i++){ g.drawLine(0,i*15,600,i*15); } //Draw 40 vertical lines for(int i = 0; i <= 40; i++){ g.drawLine(i*15,0,i*15,600); } //Draw snake LinkedList<Node> body = snake.getBody(); for(Node node : body){ g.fillRect(node.getX()*15,node.getY()*15,15,15); } //Draw food g.fillRect(food.getX()*15,food.getY()*15,15,15); } }; //Add checkerboard to form add(jPanel); } //Initialize form parameters public void initFrame(){ //Set the width and height of the form setSize(610,640); //Set the default location of the form setLocation(408,408); //Set the function of the close button setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Set form size immutable setResizable(false); } public static void main(String[] args) { //Create a form object and display it new MainFrame().setVisible(true); } }