Maison >Java >javaDidacticiel >Tutoriel sur l'écriture de petits jeux en Java : No Snake Game
Coordonnée Point.java
Enregistrez les valeurs des coordonnées horizontales et verticales.package cn.xeblog.snake.model; import java.util.Objects; /** * 坐标 * * @author anlingyi * @date 2022/8/2 3:35 PM */ public class Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Point point = (Point) o; return x == point.x && y == point.y; } @Override public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } }
Moving direction Direction.java
Fournit une énumération de quatre directions de déplacement : haut, bas, gauche et droite.package cn.xeblog.snake.model; /** * @author anlingyi * @date 2022/8/2 5:25 PM */ public enum Direction { UP, DOWN, LEFT, RIGHT }
Snake.java
stocke les informations sur les coordonnées du corps du serpent, fournit le mouvement du corps du serpent, supprime les coordonnées de la queue du serpent et obtient la tête et le serpent du serpent coordonnées de la queue, longueur du corps du serpent et autres méthodes. Voici le principe du mouvement du serpent :Lorsque le jeu démarre, une direction de déplacement sera fixée, et le serpent se déplacera toujours dans cette direction. Nous pouvons changer la direction de déplacement du serpent. serpent à l'aide des touches de direction. , le mouvement du serpent consiste en fait à déplacer les coordonnées du corps du serpent. Par exemple, la longueur du corps du serpent (à l'exclusion de la tête du serpent) est de 6. Lors du déplacement, il vous suffit de déplacer le. coordonnées du corps du serpent en position 5 aux coordonnées de la position 6. La position Pour déplacer la coordonnée de la position 4 vers la coordonnée de la position 5, en termes simples, cela signifie changer la coordonnée précédente par celle située derrière. mouvement du corps du serpent. Le mouvement de la tête du serpent doit être calculé séparément. S'il se déplace vers le haut et vers le bas, alors c'est l'opération d'addition et de soustraction de la coordonnée y. Pour se déplacer vers le haut, vous devez soustraire la coordonnée y. hauteur du corps du serpent. Au contraire, pour descendre, vous devez ajouter la hauteur du corps du serpent. La même chose s'applique aux mouvements à gauche et à droite.
package cn.xeblog.snake.model; import java.util.List; /** * 蛇 * * @author anlingyi * @date 2022/8/2 3:32 PM */ public class Snake { public static int width = 10; public static int height = 10; /** * 蛇身坐标列表 */ public List<Point> body; public Snake(List<Point> body) { this.body = body; } /** * 添加蛇身坐标 * * @param x * @param y */ public void add(int x, int y) { this.body.add(new Point(x * width, y * height)); } /** * 移除蛇尾坐标 */ public void removeLast() { int size = size(); if (size == 0) { return; } this.body.remove(size - 1); } /** * 获取蛇头坐标 * * @return */ public Point getHead() { if (size() > 0) { return this.body.get(0); } return null; } /** * 获取蛇尾坐标 * * @return */ public Point getTail() { int size = size(); if (size > 0) { return this.body.get(size - 1); } return null; } /** * 蛇身长度 * * @return */ public int size() { return this.body.size(); } /** * 蛇移动 * * @param direction 移动方向 */ public void move(Direction direction) { if (size() == 0) { return; } for (int i = this.size() - 1; i > 0; i--) { // 从蛇尾开始向前移动 Point point = this.body.get(i); Point nextPoint = this.body.get(i - 1); point.x = nextPoint.x; point.y = nextPoint.y; } // 蛇头移动 Point head = getHead(); switch (direction) { case UP: head.y -= height; break; case DOWN: head.y += height; break; case LEFT: head.x -= width; break; case RIGHT: head.x += width; break; } } }
Pill Pill.java
stocke les coordonnées et les informations de type de "pilule".package cn.xeblog.snake.model; /** * 药丸 * * @author anlingyi * @date 2022/8/2 4:49 PM */ public class Pill { public static int width = 10; public static int height = 10; /** * 坐标 */ public Point point; /** * 药丸类型 */ public PillType pillType; public enum PillType { /** * 红色药丸 */ RED(5), /** * 蓝色药丸 */ BLUE(2), /** * 绿色药丸 */ GREEN(1), ; /** * 分数 */ public int score; PillType(int score) { this.score = score; } } public Pill(int x, int y, PillType pillType) { this.point = new Point(x * width, y * height); this.pillType = pillType; } }Interface de jeuInitialiser certaines informations, telles que la largeur et la hauteur de l'interface de jeu, les minuteries, certains indicateurs d'état (si arrêter le jeu, si le jeu est gagné), et surveillez certains événements clés (la barre d'espace démarre/met en pause le jeu et les quatre touches de direction contrôlent la direction du mouvement du serpent), et dessine l'écran de jeu. Lorsqu'il est détecté que le jeu démarre, les informations de localisation du serpent et de la "pilule" sont initialisées, puis le chronomètre démarre pour redessiner l'écran de jeu de temps en temps afin que le serpent peut bouger. Lorsqu'il est détecté qu'un serpent se mord ou qu'un serpent heurte un mur, l'état du jeu sera marqué comme "Échec du jeu", l'écran de fin du jeu sera dessiné et le chronomètre s'arrêtera. Si le corps du serpent est 0, alors le jeu est terminé et le statut du jeu est marqué comme « Jeu gagné ».
package cn.xeblog.snake.ui; import cn.xeblog.snake.model.Direction; import cn.xeblog.snake.model.Pill; import cn.xeblog.snake.model.Point; import cn.xeblog.snake.model.Snake; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.Collections; import java.util.Random; /** * @author anlingyi * @date 2022/8/2 3:51 PM */ public class SnakeGameUI extends JPanel implements ActionListener { /** * 宽度 */ private int width; /** * 高度 */ private int height; /** * 蛇 */ private Snake snake; /** * 药丸 */ private Pill pill; /** * 移动方向 */ private Direction direction; /** * 停止游戏标记 */ private boolean stop; /** * 游戏状态 0.初始化 1.游戏胜利 2.游戏失败 */ private int state = -1; /** * 定时器 */ private Timer timer; /** * 移动速度 */ private int speed = 100; /** * 分数 */ private int score; /** * 特殊药丸列表 */ private ArrayList<Pill.PillType> specialPill; public SnakeGameUI(int width, int height) { this.width = width; this.height = height; this.timer = new Timer(speed, this); this.stop = true; initPanel(); } /** * 初始化 */ private void init() { this.score = 0; this.state = 0; this.stop = true; this.timer.setDelay(speed); initSnake(); initPill(); generatePill(); repaint(); } /** * 初始化游戏面板 */ private void initPanel() { this.setPreferredSize(new Dimension(this.width, this.height)); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (stop && e.getKeyCode() != KeyEvent.VK_SPACE) { return; } switch (e.getKeyCode()) { case KeyEvent.VK_UP: if (direction == Direction.DOWN) { break; } direction = Direction.UP; break; case KeyEvent.VK_DOWN: if (direction == Direction.UP) { break; } direction = Direction.DOWN; break; case KeyEvent.VK_LEFT: if (direction == Direction.RIGHT) { break; } direction = Direction.LEFT; break; case KeyEvent.VK_RIGHT: if (direction == Direction.LEFT) { break; } direction = Direction.RIGHT; break; case KeyEvent.VK_SPACE: if (state != 0) { init(); } stop = !stop; if (!stop) { timer.start(); } break; } } }); } /** * 初始化蛇 */ private void initSnake() { this.direction = Direction.LEFT; int maxX = this.width / Snake.width; int maxY = this.height / Snake.height; this.snake = new Snake(new ArrayList<>()); this.snake.add(maxX - 2, 3); this.snake.add(maxX - 1, 3); this.snake.add(maxX - 1, 2); this.snake.add(maxX - 1, 1); for (int i = maxX - 1; i > 0; i--) { this.snake.add(i, 1); } for (int i = 1; i < maxY - 1; i++) { this.snake.add(1, i); } for (int i = 1; i < maxX - 1; i++) { this.snake.add(i, maxY - 2); } } /** * 初始化药丸 */ private void initPill() { this.specialPill = new ArrayList<>(); for (int i = 0; i < 5; i++) { this.specialPill.add(Pill.PillType.RED); } for (int i = 0; i < 10; i++) { this.specialPill.add(Pill.PillType.BLUE); } Collections.shuffle(specialPill); } /** * 生成药丸 */ private void generatePill() { // 是否获取特殊药丸 boolean getSpecialPill = new Random().nextInt(6) == 3; Pill.PillType pillType; if (getSpecialPill && this.specialPill.size() > 0) { // 生成特殊药丸 int index = new Random().nextInt(this.specialPill.size()); pillType = this.specialPill.get(index); this.specialPill.remove(index); } else { // 生成绿色药丸 pillType = Pill.PillType.GREEN; } // 随机坐标 int x = new Random().nextInt(this.width / Pill.width - 1); int y = new Random().nextInt(this.height / Pill.height - 1); this.pill = new Pill(x, y, pillType); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(new Color(66, 66, 66)); g2.fillRect(0, 0, this.width, this.height); if (this.snake != null) { // 画蛇 g2.setColor(new Color(255, 255, 255)); for (int i = this.snake.size() - 1; i >= 0; i--) { Point point = this.snake.body.get(i); if (i == 0) { // 蛇头 g2.setColor(new Color(255, 92, 92)); } else { g2.setColor(new Color(215, 173, 173)); } g2.fillRect(point.x, point.y, Snake.width, Snake.height); } } if (this.pill != null) { // 画药丸 Color pillColor; switch (this.pill.pillType) { case RED: pillColor = new Color(255, 41, 41); break; case BLUE: pillColor = new Color(20, 250, 243); break; default: pillColor = new Color(97, 255, 113); break; } g2.setColor(pillColor); g2.fillOval(pill.point.x, pill.point.y, Pill.width, Pill.height); } if (state > 0) { // 显示游戏结果 String tips = "游戏失败!"; if (state == 1) { tips = "游戏胜利!"; } g2.setFont(new Font("", Font.BOLD, 20)); g2.setColor(new Color(208, 74, 74)); g2.drawString(tips, this.width / 3, this.height / 3); g2.setFont(new Font("", Font.PLAIN, 18)); g2.setColor(Color.WHITE); g2.drawString("得分:" + this.score, this.width / 2, this.height / 3 + 50); } if (stop) { g2.setFont(new Font("", Font.PLAIN, 18)); g2.setColor(Color.WHITE); g2.drawString("按空格键开始/暂停游戏!", this.width / 4, this.height - 50); } } @Override public void actionPerformed(ActionEvent e) { // 是否吃药 boolean isAte = false; if (!this.stop) { // 移动蛇 this.snake.move(this.direction); Point head = this.snake.getHead(); if (head.equals(this.pill.point)) { // 吃药了 isAte = true; // 药丸分数 int getScore = this.pill.pillType.score; // 累计分数 this.score += getScore; for (int i = 0; i < getScore; i++) { // 移除蛇尾 this.snake.removeLast(); if (this.snake.size() == 0) { // 游戏胜利 this.state = 1; this.stop = true; break; } } pill = null; if (this.score % 10 == 0) { int curSpeed = this.timer.getDelay(); if (curSpeed > 30) { // 加速 this.timer.setDelay(curSpeed - 10); } } } if (state == 0) { // 判断蛇有没有咬到自己或是撞墙 int maxWidth = this.width - this.snake.width; int maxHeight = this.height - this.snake.height; boolean isHitWall = head.x > maxWidth || head.x < 0 || head.y > maxHeight || head.y < 0; boolean isBiting = false; for (int i = this.snake.size() - 1; i > 0; i--) { if (head.equals(this.snake.body.get(i))) { isBiting = true; break; } } if (isHitWall || isBiting) { // 游戏失败 this.state = 2; this.stop = true; } } } if (this.stop) { this.timer.stop(); } else if (isAte) { // 重新生成药丸 generatePill(); } repaint(); } }Catégorie StartupEntrée de démarrage du jeu.
package cn.xeblog.snake; import cn.xeblog.snake.ui.SnakeGameUI; import javax.swing.*; /** * 启动游戏 * * @author anlingyi * @date 2022/8/2 3:41 PM */ public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); frame.setResizable(false); frame.setTitle("不贪吃蛇"); frame.setSize(400, 320); frame.setLocationRelativeTo(null); JPanel gamePanel = new SnakeGameUI(400, 300); frame.add(gamePanel); gamePanel.requestFocus(); } }
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!