Maison  >  Article  >  Java  >  Comment implémenter le mini-jeu Snake War en Java

Comment implémenter le mini-jeu Snake War en Java

WBOY
WBOYavant
2023-04-26 08:55:061809parcourir

1. Environnement de développement et affichage du jeu

Snake Battle doit être effectué dans le système Windows 10 pendant le processus de conception et d'expérimentation, et l'outil de développement IntelliJ IDEA Community Edition 2020.3.2 (jdk-15) est utilisé pour terminer le processus. écriture de code, compilation, débogage, tests et autres travaux. Les composants requis par le programme, tels que les images de la tête, du corps et de l'arrière-plan du serpent, sont tous produits à l'aide du logiciel d'image Adobe Photoshop 2020.

1.1 Interface principale du jeu

Comment implémenter le mini-jeu Snake War en Java

1.2 Interface mobile

Comment implémenter le mini-jeu Snake War en Java

1.3 Interface de récompenses

1 Le jeu atteint 50 points :

Comment implémenter le mini-jeu Snake War en Java

2. 100 points :

Comment implémenter le mini-jeu Snake War en Java

Interface de fonction d'accélération 1.4 F

Lorsque vous appuyez sur F, la vitesse augmente jusqu'à 100.

Comment implémenter le mini-jeu Snake War en Java

1.5 Interface de la mort

Comment implémenter le mini-jeu Snake War en Java

2. Analyse de la demande

Le jeu Snake est un petit jeu de puzzle qui peut être utilisé dans les loisirs quotidiens, les divertissements et d'autres scénarios. Cette conception de jeu implique la connaissance des tableaux unidimensionnels, des composants communs dans Swing, du traitement des événements dans l'interface graphique (écouteurs d'événements, écouteurs de clavier), de l'encapsulation et de l'héritage de classes, des variables statiques, des classes d'empaquetage, des nombres aléatoires, etc.

Les exigences spécifiques sont résumées comme suit :

1. L'interface d'initialisation a une taille de 800 × 800, et l'interface de jeu doit être conservée au centre de l'écran et la fenêtre doit contenir le mot « Snake » ;

2. L'interface de jeu doit avoir le texte d'invite nécessaire, indiquer le score du jeu et la vitesse actuelle du serpent. L'interface de démarrage doit avoir un texte d'invite d'opération (appuyez sur le jeu spatial pour démarrer/mettre en pause le jeu, appuyez et maintenez F pour accélérer), et la couleur du texte doit être belle

3. le panneau), la position du serpent dans le sens du programme (par défaut à droite), la longueur du serpent (par défaut 3) et initialiser la position de la nourriture

Mise en œuvre du démarrage et de la pause du jeu : contrôler le démarrage et la pause du jeu ; via la barre d'espace ;

5. Mouvement du serpent Mise en œuvre de la fonction : Utilisez W, S, A, D ou ↑, ↓, ←, → , et à droite pour jouer au jeu ;

6. Lorsque la tête du serpent touche la périphérie de l'activité : Lorsque la tête du serpent touche l'extrémité la plus à droite (gauche) de l'interface, elle apparaîtra depuis l'extrémité symétrique gauche (droite), et ainsi de suite. Lorsque la tête du serpent touche l'extrémité supérieure (inférieure) de l'interface, elle apparaîtra à partir de l'extrémité inférieure (supérieure) symétrique

7. la tête du serpent touche la nourriture, elle mange la nourriture. A ce moment, la longueur du serpent doit être augmentée de 1, la vitesse doit être augmentée de 10, le score doit être augmenté de 10 et la position de la nourriture est rafraîchie (position aléatoire) ; la fonction d'accélération du serpent : lorsque la touche "F" est enfoncée, le serpent accélère. , la valeur de vitesse atteint 100 ; lorsque vous relâchez la touche "F", le serpent revient à la vitesse par défaut de 10 ; : lorsque la tête du serpent touche le corps du serpent, le serpent meurt, le jeu se termine et l'interface se rapproche de l'invite centrale : "Votre petit serpent est mort, appuyez sur espace pour recommencer !"; mécanisme de récompense du jeu : lorsque le score est de 10, le jeu demande le mot « Bien ! » ; lorsque le score est de 50, le jeu demande « Bon !!! » ; " ; lorsque le score atteint 200, le jeu affiche " Unstoppable !!! »

3.1 Conception fonctionnelle globale du système

Ce programme Snake comprend généralement la fonction mobile de Snake et la fonction d'accélération d'initiative de Snake, la fonction de jugement des règles du jeu, la fonction de contrôle de l'interface principale et la fonction de consommation de serpent gourmand. Parmi eux, la fonction de mouvement du serpent comprend le contrôle clé de la direction du mouvement et le mouvement automatique du serpent ; la fonction de jugement des règles du jeu comprend le jugement de mort du serpent, le jugement de démarrage et de pause du jeu, ainsi que les règles hors limites ; la fonction de contrôle de l'interface principale comprend l'initialisation du serpent et l'initialisation de la nourriture ; les fonctions d'un serpent gourmand mangeant de la nourriture incluent la croissance du corps du serpent, l'augmentation de la vitesse du serpent, l'augmentation des points et la position de rafraîchissement de la nourriture. Le schéma de structure fonctionnelle spécifique est le suivant :

3.2 Conception globale du processus du système

Lorsque vous entrez dans le programme Snake, déterminez d'abord si la barre d'espace est enfoncée. Si la barre d'espace est enfoncée, le jeu démarre. Après le début du jeu, il est déterminé s'il y a une entrée de touche. S'il y a une entrée de touche, la direction de déplacement du serpent est modifiée ou accélérée en fonction des paramètres de touche. S'il n'y a pas d'opération de touche, le serpent continue de se déplacer ; orientation originale. Pendant le mouvement du serpent, on juge si le serpent a mangé de la nourriture. S'il mange de la nourriture, le score du jeu sera augmenté de 10, et la vitesse de déplacement du serpent augmentera également en conséquence, que le serpent ait mangé de la nourriture ou non ; être jugé si le serpent meurt. S'il meurt, le jeu se termine ; si le serpent n'est pas mort, il continuera à juger s'il y a une entrée spatiale, le jeu sera mis en pause. il continuera à juger les pressions sur les boutons, changera l'état de mouvement du serpent en fonction des boutons et continuera le jeu jusqu'à ce que le serpent meure et que le jeu se termine.

Comment implémenter le mini-jeu Snake War en Java

4. Conception fonctionnelle

4.1 Conception de la fonction de mouvement et d'accélération du serpent

La fonction de mouvement du serpent repose principalement sur des instructions de sélection et des moniteurs de clavier, en utilisant W, S, A, D ou &uarr ;, ↓, ←, → Contrôlez la direction du mouvement du serpent vers le haut, le bas, la gauche et la droite pour jouer. Lorsque la touche F est enfoncée, le serpent accélère.

Comment implémenter le mini-jeu Snake War en Java

4.2 Conception d'un serpent gourmand mangeant de la nourriture et d'une fonction de détermination de la mort

Dans le processus de serpent gourmand mangeant de la nourriture et de détermination de la mort, les paramètres suivants sont utilisés :

  • Un paramètre de la classe Timer : type int time, la méthode timer.setDelay(time) est appelée dans le programme pour modifier les paramètres de la minuterie (plus le temps est petit, plus le serpent se déplace vite

  • Paramètres pour enregistrer si le serpent est mort ou non) ; type booléen isDied (vrai, le serpent meurt), si faux, le serpent vivra), la valeur par défaut est false

  • Longueur du serpent : longueur de type int (initialement 3) ; (initialement 0), le programme boucle le contrôle à chaque fois que vous mangez de la nourriture pour ajouter 10 points

  • Les coordonnées de la tête du serpent : serpentX[0] et serpentY[0] de type int, qui stockent l'horizontale et la verticale ; coordonnées de la tête du serpent respectivement

  • Les coordonnées du corps du serpent : int[] Tapez serpentX[i] et serpentY[i] stockent respectivement les coordonnées horizontales et verticales de chaque corps de serpent (i≠0) ;

  • Coordonnées de la nourriture : les types int foodX et foodY stockent respectivement les coordonnées horizontales et verticales de la nourriture. Les coordonnées, foodX et foodY sont tous des nombres aléatoires générés à l'aide de la méthode nextInt() dans la classe Random, donc les coordonnées de la nourriture sont aléatoire.
  • Je n'entrerai pas dans les détails lors de l'utilisation des paramètres ci-dessus ci-dessous.
  • 4.2.1 Conception de la fonction d'accélération de consommation de nourriture du serpent gourmand

  • Lorsque les coordonnées de la tête de serpent serpentX[0] et serpentY[0] sont égales aux coordonnées de nourritureX et nourritureY respectivement, le score augmente de 10 et la longueur du corps du serpent augmente 1. Diminuez le temps du paramètre Minuterie de 10 pour compléter les points supplémentaires après que le serpent ait mangé de la nourriture, allongez le corps du serpent et accélérez la fonction. Le diagramme de conception de flux de cette fonction est le suivant :

4.2.2 Conception de la fonction de détermination de la mort du serpent

Lorsque le serpent gourmand se mange, le serpent meurt, c'est-à-dire que la tête du serpent coordonne le serpentX[0] et serpentY[0] Lorsqu'ils sont égaux aux coordonnées du corps du serpent serpentX[i] et serpentY[i] respectivement, le serpent meurt. À ce moment-là, isDied=! est décédé.

Comment implémenter le mini-jeu Snake War en Java

4.3 Conception de la fonction d'accélération active de Snake

La fonction d'accélération active de Snake signifie que si vous maintenez la touche F enfoncée pendant le jeu, le serpent se déplacera plus rapidement. Si vous la maintenez enfoncée et la relâchez, le serpent se déplacera. plus rapidement. Ceci est principalement réalisé via l'écouteur de clavier dans l'interface graphique. Deux méthodes d'écoute de clavier sont implémentées, keyPressed() et keyReleased() surveillant respectivement l'opération consistant à appuyer sur la touche F et à relâcher la touche F. Deuxièmement, le paramètre time est utilisé. Dans le programme, la valeur du time est modifiée en appelant la méthode timer.setDelay(time) (timer est un objet de la classe Timer) pour modifier la fréquence de la minuterie, obtenant ainsi l'effet. d'accélérer le serpent.

Comment implémenter le mini-jeu Snake War en Java

4.4 Conception de la fonction du mécanisme de récompense du serpent

La fonction du mécanisme de récompense du serpent est principalement implémentée à l'aide de la structure de sélection et de l'outil pinceau dans la méthode paintComponent(Graphics g). Lorsque le jeu atteint un certain score, le programme appellera la méthode g.drawString("XXX", serpentX[0], serpentY[0]) dans l'outil pinceau pour dessiner un texte d'invite à la position de la tête du serpent.

Comment implémenter le mini-jeu Snake War en Java

5. Structure du projet et mise en œuvre du projet

5.1 Structure du projet et relations entre les classes

Comment implémenter le mini-jeu Snake War en Java

5.2 Code source complet du projetComment implémenter le mini-jeu Snake War en Java

5.2.1 Classe d'images

Cette classe est une classe statique, qui stocke principalement les objets image du composant Snake.

package snakegame;

import javax.swing.*;
import java.net.URL;

//Images类用于封装图片路径以及获取图片(使用静态对象便于用类名直接访问)
public class Images {
    //将图片的路径封装成一个对象
    public static URL bodyURL=Images.class.getResource("/snake_images/body.jpg");
    public static URL backURL=Images.class.getResource("/snake_images/back.jpg");
    public static URL snakeDownURL=Images.class.getResource("/snake_images/snakeDown.jpg");
    public static URL snakeLeftURL=Images.class.getResource("/snake_images/snakeLeft.jpg");
    public static URL snakeRightURL=Images.class.getResource("/snake_images/snakeRight.jpg");
    public static URL snakeUpURL=Images.class.getResource("/snake_images/snakeUp.png");
    public static URL foodURL=Images.class.getResource("/snake_images/food.jpg");
    //将图片封装为程序中的对象
    public static ImageIcon bodyImg=new ImageIcon(bodyURL);
    public static ImageIcon backImg=new ImageIcon(backURL);
    public static ImageIcon snakeDownImg=new ImageIcon(snakeDownURL);
    public static ImageIcon snakeUpImg=new ImageIcon(snakeUpURL);
    public static ImageIcon snakeRightImg=new ImageIcon(snakeRightURL);
    public static ImageIcon snakeLeftImg=new ImageIcon(snakeLeftURL);
    public static ImageIcon foodImg=new ImageIcon(foodURL);
}

5.2.2 HighestScore

Cette classe implémente la fonction de score le plus élevé de l'histoire.

package snakegame;

import org.w3c.dom.Text;

import java.io.*;

//该类用于给游戏添加历史最高分功能
public class HighestScore {
    static int score = 0;//最高分的存储

    public void highest() throws IOException {
        //得分为最高分时存储
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(String.valueOf(Text.class.getResourceAsStream("贪吃蛇大作战/score.txt"))));
        if (GamePanel.score > score) {
            score = GamePanel.score;
            String s1 = String.valueOf(score);
            bos.write(s1.getBytes());
        }
        bos.close();
    }

    //用于游戏开始时从文件读取最高分的值
    public void readHighest() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(String.valueOf(Text.class.getResourceAsStream("贪吃蛇大作战/score.txt"))));
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));//测试用
            String s2 = new String(bys, 0, len);
            score = Integer.valueOf(s2);
        }
        bis.close();
    }
}

5.2.3 Classe GamePanel

Cette classe est utilisée pour dessiner le panneau de jeu Snake et implémenter des fonctions logiques spécifiques du jeu.

package snakegame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.Random;

//贪吃蛇游戏面板的绘制
public class GamePanel extends JPanel {
    Timer timer;
    int time=100;
    static int score;//记录游戏分数
    //蛇属性部分
    boolean isDied;
    int length;//设置蛇长
    String direction;//蛇头朝向
    //分别储存蛇身的X,Y坐标
    int[] snakeX=new int[300];
    int[] snakeY=new int[300];
    //判断游戏是否开始
    boolean isStart=false;
    int foodX,foodY;//食物的X,Y坐标
    //贪吃蛇初始化方法
    public void init(){
        length=3;
        snakeX[0]=175;
        snakeY[0]=275;
        snakeX[1]=150;
        snakeY[1]=275;
        snakeX[2]=125;
        snakeY[2]=275;
        foodX=300;
        foodY=400;
        score=0;
        isDied=false;//蛇默认状态为活着
        direction="R";//U,D,L,R分别表示蛇头朝向上,下,左,右
    }

    //构造方法
    public GamePanel() throws IOException {
        init();

        if(GamePanel.score>HighestScore.score){
            new HighestScore().highest();
        }
        //焦点定位到当前面板
        this.setFocusable(true);
        //监听器的实现部分
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                int keyCode = e.getKeyCode();
                //按下空格以开始游戏,以及方向键的控制
                if (keyCode == KeyEvent.VK_SPACE) {
                    if(isDied){
                        init();
                    }else {
                        isStart = !isStart;
                        repaint();//重绘
                    }
                } else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_W) {
                    direction = "U";
                } else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_S) {
                    direction = "D";
                } else if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_A) {
                    direction = "L";
                } else if (keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_D) {
                    direction = "R";
                }
            }
        });
        //贪吃蛇加速功能的实现
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode=e.getKeyCode();
                if(keyCode==KeyEvent.VK_F){
                    time=10;
                    timer.setDelay(time);//按下F时加速
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode=e.getKeyCode();
                if(keyCode==KeyEvent.VK_F){
                    time=100;
                    timer.setDelay(time);//松开F键减速恢复默认速度
                }
            }
        });
        //对定时器进行初始化,并实现监听器
            timer = new Timer(time, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    //当游戏处于开始状态且蛇活着时蛇活动,且后一节身子到前一节身子的位置上(每一节身子为25乘25像素)
                    if (isStart && isDied == false) {
                        //蛇身运动部分
                        for (int i = length - 1; i > 0; i--) {
                            snakeX[i] = snakeX[i - 1];
                            snakeY[i] = snakeY[i - 1];
                        }
                        //蛇头运动部分
                        if ("D".equals(direction)) {
                            snakeY[0] += 25;
                        }
                        if ("U".equals(direction)) {
                            snakeY[0] -= 25;
                        }
                        if ("L".equals(direction)) {
                            snakeX[0] -= 25;
                        }
                        if ("R".equals(direction)) {
                            snakeX[0] += 25;
                        }
                        //防止超出边界
                        if (snakeX[0] > 750) {
                            snakeX[0] = 25;
                        }
                        if (snakeX[0] < 25) {
                            snakeX[0] = 750;
                        }
                        if (snakeY[0] < 100) {
                            snakeY[0] = 725;
                        }
                        if (snakeY[0] > 725) {
                            snakeY[0] = 100;
                        }
                        //吃食物的动作,吃食物加10分且蛇身变长,蛇的速度提升10
                        if ((snakeX[0] == foodX && snakeY[0] == foodY)) {
                            length++;//蛇身长度加1
                            foodX = (new Random().nextInt(30) + 1) * 25;//随机生成X坐标[25,750]
                            foodY = (new Random().nextInt(26) + 4) * 25;//随机生成Y坐标[100,725]
                            score += 10;//吃一次食物积分加10
                            try {
                                new HighestScore().highest();
                            } catch (IOException ioException) {
                                ioException.printStackTrace();
                            }
                            if(time>10)
                                timer.setDelay(time-=10);//吃一次食物速度增加10
                        }
                        //蛇的死亡机制判定
                        for (int i = 1; i < length; i++) {
                            if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                                isDied = !isDied;
                            }
                        }
                        repaint();
                    }
                }
            });
            timer.start();//定时器启动
    }

    //绘制面板部分
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        //填充背景颜色
        this.setBackground(new Color(164, 219, 246));
        //绘制初始蛇头的图片(默认右方朝向)
        Images.backImg.paintIcon(this,g,10,10);
        //调整画笔的颜色并绘制一个矩形面板
        g.setColor(new Color(219,226,219));
        g.fillRect(10,70,770,685);
        //蛇头的绘制;上下左右不同情况
        if("L".equals(direction)){
            Images.snakeLeftImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if("R".equals(direction)){
            Images.snakeRightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if("U".equals(direction)){
            Images.snakeUpImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        if("D".equals(direction)){
            Images.snakeDownImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        }
        //蛇身的绘制
        for(int i=1;i<length;i++) {
            Images.bodyImg.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        //食物绘制
       Images.foodImg.paintIcon(this,g,foodX,foodY);
        //游戏的文字提示语
        if(!isStart&&!isDied){
            g.setColor(new Color(12, 191, 222));
            g.setFont(new Font("楷体",Font.BOLD,40));
            g.drawString("轻按空格以开始/暂停游戏!",150,330);
            g.setColor(new Color(246, 2, 31));
            g.setFont(new Font("宋体",Font.CENTER_BASELINE,30));
            g.drawString("按住F以加速",300,380);
        }
        //游戏的得分显示
        g.setColor(new Color(248, 4, 74));
        g.setFont(new Font("楷体",Font.BOLD,30));
        g.drawString("得分:"+score,420,90);
        //游戏的最高分展示模块
        try {
            new HighestScore().readHighest();
        } catch (IOException e) {
            e.printStackTrace();
        }
        g.setColor(new Color(183, 25, 238));
        g.setFont(new Font("楷体",Font.BOLD,30));
        g.drawString("历史最高分:"+HighestScore.score,10,90);
        //蛇的速度提示
        g.setColor(new Color(248, 136, 36));
        g.setFont(new Font("楷体",Font.BOLD,30));
        g.drawString("当前速度:"+String.valueOf(110-time),550,90);
        //游戏的奖励鼓励机制
        if(score==10){
            g.setColor(new Color(127, 232, 20));
            g.setFont(new Font("微软雅黑",Font.BOLD,50));
            g.drawString("Good!",snakeX[0],snakeY[0]);
        }
        else if(score==50){
            g.setColor(new Color(17, 231, 250));
            g.setFont(new Font("微软雅黑",Font.BOLD,50));
            g.drawString("Good!!!",snakeX[0],snakeY[0]);
        }else if(score==100){
            g.setColor(new Color(248, 196, 6));
            g.setFont(new Font("微软雅黑",Font.BOLD,50));
            g.drawString("Perfect!!!",snakeX[0],snakeY[0]);
        }else if(score==200){
            g.setColor(new Color(248, 245, 26));
            g.setFont(new Font("微软雅黑",Font.BOLD,50));
            g.drawString("无人能挡!!!",snakeX[0],snakeY[0]);
        }
        //小蛇死亡时面板的绘制
        if(isDied){
            g.setColor(new Color(6, 115, 248));
            g.setFont(new Font("微软雅黑",Font.BOLD,30));
            g.drawString("你的小蛇已经死亡,按下空格重新开始!",170,330);
        }
    }
}

5.2.4 Début du cours

La disposition générale de la page et l'entrée du programme.

package snakegame;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;

//贪吃蛇总体界面布局以及程序的主方法
public class Start {
    public static void main(String[] args) throws IOException {
        JFrame jf=new JFrame("贪吃蛇");
        //获取屏幕的大小,并使用数据使窗口位置居中
        int width= Toolkit.getDefaultToolkit().getScreenSize().width;
        int height= Toolkit.getDefaultToolkit().getScreenSize().height;
        jf.setBounds((width-800)/2,(height-800)/2,800,800);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setResizable(false);//设置窗口大小不能更改
        //添加GamePanel面板
        GamePanel panel=new GamePanel();
        jf.add(panel);
        jf.setVisible(true);
    }
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer