嘉兴高端网站建设,凡科门店通,电商网站开发计划,网络游戏电脑版排行榜简介
简易贪吃蛇#xff0c;使用 javax.swing 组件构建游戏界面#xff0c;通过监听键盘按键实现游戏操纵。
功能设计
按1 - 开始游戏按2 - 重新开始按3 - 暂停/继续按Esc-退出游戏统计吃到的苹果个数#xff08;得分#xff09;难度控制#xff0c;得分超过阈值时难度…简介
简易贪吃蛇使用 javax.swing 组件构建游戏界面通过监听键盘按键实现游戏操纵。
功能设计
按1 - 开始游戏按2 - 重新开始按3 - 暂停/继续按Esc-退出游戏统计吃到的苹果个数得分难度控制得分超过阈值时难度增加蛇身移动速度加快
实现
定义 SnakeGame 类 继承 JPanel 类 重写其由 JComponent 类中继承的 paintComponent 方法在此方法中进行图像的绘制。 实现 ActionListener 类 实现其 actionPerformed 方法 通过监听在 SnakeGame 类中的Timer 计时器步长内按键的输入完成对图像的操作。
public class SnakeGame extends JPanel implements ActionListener {//(timer new Timer(delay, this)).start();public void paintComponent(Graphics g) {//在这里操作图像的绘制蛇身和苹果等}public void actionPerformed(ActionEvent e) {//在这里通过对定时器的监听完成对图像的操作}}自定义按键适配器 将键盘输入转换为程序识别的方向值同时记录键盘输入。 /*** 定义方向*/
public interface Direction {char LEFT L;char RIGHT R;char UP U;char DOWN D;}/*** 按键适配器用于监听输入按键*/
public class MyKeyAdapter extends KeyAdapter {public void keyPressed(KeyEvent e) {int keyCode e.getKeyCode();eventKeyCode e.getKeyCode();if ((keyCode KeyEvent.VK_LEFT || keyCode KeyEvent.VK_A) direction ! Direction.RIGHT) {direction Direction.LEFT;} else if ((keyCode KeyEvent.VK_RIGHT || keyCode KeyEvent.VK_D) direction ! Direction.LEFT) {direction Direction.RIGHT;} else if ((keyCode KeyEvent.VK_UP || keyCode KeyEvent.VK_W) direction ! Direction.DOWN) {direction Direction.UP;} else if ((keyCode KeyEvent.VK_DOWN || keyCode KeyEvent.VK_S) direction ! Direction.UP) {direction Direction.DOWN;}}
}
在 paintComponent 和 actionPerformed 方法中实现游戏逻辑。
注意
对可用像素点的处理可用像素点个数 屏幕长 * 屏幕宽 / 单位大小苹果大小。对蛇身初始坐标的处理 存储蛇身的初始坐标须在可用像素点中。对苹果坐标的处理需判断新的苹果坐标是否在蛇身内。对游戏是否存活的处理蛇头撞到蛇身或者蛇头撞到边缘都应视为结束。对接收到的按键值的处理除方向按键外其余按键值使用完之后需做清除。
完整实现代码如下
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.util.Arrays;
import java.util.Random;public class SnakeGame extends JPanel implements ActionListener {public interface Direction {char LEFT L;char RIGHT R;char UP U;char DOWN D;}public interface RunStatus {char READY 0; // 就绪char RUN 1; // 运行char OVER 2; // 失败char PAUSE 3; // 暂停/继续}final Random random new Random();volatile int eventKeyCode;//记时步长volatile int delay 150;Timer timer null;//屏幕大小static final int SCREEN_WIDTH 600;static final int SCREEN_HEIGHT 600;//可用像素点static final int UNIT_SIZE 25;static final int GAME_UNITS (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;//蛇身volatile int bodyParts;int snakeBodyX[];int snakeBodyY[];//目标int appleX;int appleY;//得分volatile int applesEaten;volatile char direction;volatile char runStatus;SnakeGame() {this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));this.setFocusable(true);this.addKeyListener(new MyKeyAdapter());(timer new Timer(delay, this)).start();init();}public void init() {bodyParts 1;snakeBodyX new int[GAME_UNITS];Arrays.fill(snakeBodyX, -1);snakeBodyX[0] 0;snakeBodyY new int[GAME_UNITS];Arrays.fill(snakeBodyY, -1);snakeBodyY[0] 0;appleX nextCoordinate(SCREEN_WIDTH, snakeBodyX);appleY nextCoordinate(SCREEN_HEIGHT, snakeBodyY);applesEaten 0;direction Direction.RIGHT;runStatus RunStatus.READY;timer.setDelay(delay);}public void paintComponent(Graphics g) {super.paintComponent(g);String tip applesEaten;int y SCREEN_HEIGHT / 2 - 120;switch (runStatus) {case RunStatus.READY:drawing(g);g.setColor(Color.BLUE);g.setFont(new Font(null, Font.ITALIC, 20));g.drawString(按1-开始游戏, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));g.drawString(按2-重新开始, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));g.drawString(按3-暂停/继续, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));g.drawString(按Esc-退出游戏, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));break;case RunStatus.PAUSE:drawing(g);g.setColor(Color.BLUE);g.setFont(new Font(null, Font.ITALIC, 20));y y 80;g.drawString(按3-继续, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));g.drawString(按Esc-退出游戏, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));break;case RunStatus.RUN:drawing(g);g.setColor(Color.blue);g.setFont(new Font(null, Font.BOLD, 20));g.drawString(tip, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, g.getFont().getSize());break;case RunStatus.OVER:g.setColor(Color.RED);g.setFont(new Font(Ink Free, Font.BOLD, 40));g.drawString(Game Over, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, y - 120);g.setFont(new Font(null, Font.ITALIC, 20));g.drawString(得分 applesEaten, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, y - 60);g.setColor(Color.BLUE);g.drawString(按2-重新开始, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));g.drawString(按Esc-退出游戏, (SCREEN_WIDTH - getFontMetrics(g.getFont()).stringWidth(tip)) / 2, (y y 40));break;default:break;}}/*** 绘制蛇身和苹果** param g*/public void drawing(Graphics g) {//苹果颜色g.setColor(Color.PINK);//画苹果g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);//蛇身颜色g.setColor(Color.RED);//填充蛇身for (int i 0; i bodyParts; i) {g.fillRect(snakeBodyX[i], snakeBodyY[i], UNIT_SIZE, UNIT_SIZE);}}/*** 执行的动作* 会定时执行此方法** param e*/public void actionPerformed(ActionEvent e) {//前置事件doSomeThing();if (runStatus RunStatus.RUN) {move();//撞到边缘if (snakeBodyX[0] 0 || snakeBodyX[0] SCREEN_WIDTH || snakeBodyY[0] 0 || snakeBodyY[0] SCREEN_HEIGHT) {runStatus RunStatus.OVER;}//蛇身相撞for (int i bodyParts; i 0; i--) {if ((snakeBodyX[0] snakeBodyX[i]) (snakeBodyY[0] snakeBodyY[i])) {runStatus RunStatus.OVER;}}//得分if ((snakeBodyX[0] appleX) (snakeBodyY[0] appleY)) {applesEaten;bodyParts;//重新生成苹果appleX nextCoordinate(SCREEN_WIDTH, snakeBodyX);appleY nextCoordinate(SCREEN_HEIGHT, snakeBodyY);//预留难度设置的方法difficultySettings();}}//重新绘图, 执行 paintComponent 方法repaint();}/*** 蛇身移动*/private void move() {for (int i bodyParts; i 0; i--) {snakeBodyX[i] snakeBodyX[(i - 1)];snakeBodyY[i] snakeBodyY[(i - 1)];}switch (direction) {case Direction.UP:snakeBodyY[0] - UNIT_SIZE;break;case Direction.DOWN:snakeBodyY[0] UNIT_SIZE;break;case Direction.LEFT:snakeBodyX[0] - UNIT_SIZE;break;case Direction.RIGHT:snakeBodyX[0] UNIT_SIZE;break;default:break;}}private void doSomeThing() {if (KeyEvent.VK_ESCAPE eventKeyCode) {System.out.println(退出程序);System.exit(0);return;}if (KeyEvent.VK_1 eventKeyCode) {System.out.println(开始游戏);runStatus RunStatus.RUN;}if (KeyEvent.VK_2 eventKeyCode) {if (runStatus ! RunStatus.RUN) {System.out.println(重新开始);init();}runStatus RunStatus.RUN;}if (KeyEvent.VK_3 eventKeyCode) {if (runStatus RunStatus.RUN) {System.out.println(暂停);runStatus RunStatus.PAUSE;eventKeyCode -1;return;}if (runStatus RunStatus.PAUSE) {System.out.println(继续);runStatus RunStatus.RUN;eventKeyCode -1;return;}}eventKeyCode -1;}/*** 难度设置 默认得分超过16的倍数时速度提升1/4*/private void difficultySettings() {//难度增加 速度加快if (applesEaten % 16 0 applesEaten ! 0) {timer.setDelay(timer.getDelay() - timer.getDelay() / 4);}}/*** 下一个苹果坐标** param randomFactorint* param arr* return*/synchronized private int nextCoordinate(int randomFactorint, int[] arr) {int coordinate random.nextInt(randomFactorint / UNIT_SIZE) * UNIT_SIZE;for (int i 0; i arr.length; i) {if (arr[i] -1) {break;}if (coordinate arr[i]) {nextCoordinate(randomFactorint, arr);}}return coordinate;}/*** 按键适配器用于监听输入按键*/public class MyKeyAdapter extends KeyAdapter {public void keyPressed(KeyEvent e) {int keyCode e.getKeyCode();eventKeyCode e.getKeyCode();if ((keyCode KeyEvent.VK_LEFT || keyCode KeyEvent.VK_A) direction ! Direction.RIGHT) {direction Direction.LEFT;} else if ((keyCode KeyEvent.VK_RIGHT || keyCode KeyEvent.VK_D) direction ! Direction.LEFT) {direction Direction.RIGHT;} else if ((keyCode KeyEvent.VK_UP || keyCode KeyEvent.VK_W) direction ! Direction.DOWN) {direction Direction.UP;} else if ((keyCode KeyEvent.VK_DOWN || keyCode KeyEvent.VK_S) direction ! Direction.UP) {direction Direction.DOWN;}}}public static void main(String[] args) {JFrame frame new JFrame();frame.setTitle(贪吃蛇);SnakeGame snake new SnakeGame();frame.add(snake);frame.setResizable(false);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack();frame.setVisible(true);}
}效果展示
游戏启动 游戏暂停