Heim >Java >javaLernprogramm >Tutorial zum Schreiben kleiner Spiele in Java: No Snake Game
Koordinaten Point.java
zeichnet die horizontalen und vertikalen Koordinatenwerte auf.
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 + '}'; } }
Bewegungsrichtung Direction.java
Bietet die Aufzählung von vier Bewegungsrichtungen: nach oben, unten, links und rechts.
package cn.xeblog.snake.model; /** * @author anlingyi * @date 2022/8/2 5:25 PM */ public enum Direction { UP, DOWN, LEFT, RIGHT }
Snake Snake.java
speichert Informationen zu Schlangenkörperkoordinaten, bietet Schlangenkörperbewegungen, Entfernung von Schlangenschwanzkoordinaten, Schlangenkopf, Schlangenschwanzkoordinaten, Schlangenkörperlänge und andere Methoden.
Hier ist das Prinzip der Schlangenbewegung: Wenn das Spiel beginnt, wird eine Bewegungsrichtung festgelegt, und die Schlange bewegt sich immer in diese Richtung. Wir können die Bewegungsrichtung der Schlange über die Richtungstasten ändern Die Schlange dient tatsächlich dazu, die Koordinaten des Schlangenkörpers an die Position zu verschieben. Beispielsweise beträgt die Länge des Schlangenkörpers (ohne den Schlangenkopf) 6. Beim Verschieben müssen Sie nur die Koordinaten verschieben Bewegen Sie den Schlangenkörper von Position 5 zu den Koordinaten von Position 6 und verschieben Sie die Koordinaten von Position 4 zu Position 5. Einfach ausgedrückt bedeutet dies, die Koordinaten der vorherigen in die dahinter liegende zu ändern. Dies ist die Bewegung des Schlangenkörpers Die Bewegung des Schlangenkopfes muss separat berechnet werden. Wenn er sich nach oben und unten bewegt, handelt es sich um eine Additions- und Subtraktionsoperation der y-Koordinate. Um sich nach oben zu bewegen, muss die Höhe des Schlangenkörpers verringert werden. Im Gegenteil, um sich nach unten zu bewegen, müssen Sie die Höhe des Schlangenkörpers addieren. Dasselbe gilt für Links- und Rechtsbewegungen.
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
speichert die Koordinaten und Typinformationen von „pill“.
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; } }
Initialisieren Sie einige Informationen, wie die Breite und Höhe der Spieloberfläche, Timer, einige Statusanzeigen (ob das Spiel gestoppt werden soll, ob das Spiel gewonnen wurde) und überwachen Sie einige wichtige Ereignisse (Leertaste). Starten/Pause des Spiels, vier Richtungstasten steuern die Richtung der Schlangenbewegung) und zeichnen den Spielbildschirm.
Wenn erkannt wird, dass das Spiel beginnt, werden die Positionsinformationen der Schlange und der „Pille“ initialisiert und dann wird der Timer gestartet, um den Spielbildschirm von Zeit zu Zeit neu zu zeichnen, damit sich die Schlange bewegen kann.
Wenn festgestellt wird, dass eine Schlange Sie beißt oder eine Schlange gegen eine Wand schlägt, wird der Spielstatus als „Spiel fehlgeschlagen“ markiert, der Bildschirm „Spielende“ wird angezeigt und der Timer stoppt, wenn der Schlangenkörper auf 0 steht , das Spiel endet und der Spielstatus wird mit „Spielsieg“ markiert.
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(); } }
Eintritt zum Spiele-Startup.
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(); } }
Das obige ist der detaillierte Inhalt vonTutorial zum Schreiben kleiner Spiele in Java: No Snake Game. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!