【Java GUI 编程】实现贪吃蛇游戏

it2024-07-08  42

文章目录

一、前言二、游戏效果三、问题解析1、怎么使小蛇动起来?2、小蛇如何转弯? 四、奉上源码五、拓展

一、前言

之前学习 GUI 编程,主要总结了 AWT 中(组件,容器,面板,事件监听,文本框监听,画图类,鼠标监听,键盘监听,窗口监听) 还有 Swing (容器,面板,label ,按钮,列表,文本框等)所以综合以上知识,写一个练手的小项目,贪吃蛇

二、游戏效果

三、问题解析

1、怎么使小蛇动起来?

我们首先定义好射的属性:长度,x 坐标,y 坐标,以及蛇头方向

通过判断蛇头方向,然后画在(x0,y0) 的坐标

当然此时蛇依然不会动,通过循环把前一个坐标复制给后一个坐标,然后不断重绘,我们就可以看到一个动态的画面了 蛇头可以根据方向来进行赋值

2、小蛇如何转弯?

转弯是通过改变蛇头的属性 fx,当 fx 为 R 的时候,表示向右,L :左

那要怎么改变呢?

需要进行键盘监听,当按下 ‘左方向键’ 的时候,把 fx 设为 L,当按下 '右方向键‘ 的时候, 把 fx 设置为 L ,其余类似

失败判定,判断头部和身体是否有重叠,如果有的话,则返回 false

四、奉上源码

加载资源类

package JavaGUI.snake; import javax.swing.*; import java.net.URL; /** * @Title: * @Package * @Description: * @author: maze * @date 2020/10/21上午 9:12 */ public class Data { // 加载当前目录下的 static 文件夹功能的 header.png 图片 public static URL headerURL = Data.class.getResource("static/header.png"); public static ImageIcon header = new ImageIcon(headerURL); // 头的四个方向 public static URL upURL = Data.class.getResource("static/up.png"); public static URL downURL = Data.class.getResource("static/down.png"); public static URL leftURL = Data.class.getResource("static/left.png"); public static URL rightURL = Data.class.getResource("static/right.png"); public static ImageIcon up = new ImageIcon(upURL); public static ImageIcon down = new ImageIcon(downURL); public static ImageIcon left = new ImageIcon(leftURL); public static ImageIcon right = new ImageIcon(rightURL); //身体 public static URL bodyURL = Data.class.getResource("static/body.png"); public static ImageIcon body = new ImageIcon(bodyURL); // 食物 public static URL foodURL = Data.class.getResource("static/food.png"); public static ImageIcon food = new ImageIcon(foodURL); }

游戏界面类

package JavaGUI.snake; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Random; /** * @Title: GamePane * @Package * @Description: * @author: maze * @date 2020/10/21上午 8:57 */ public class GamePanel extends JPanel implements KeyListener, ActionListener { // 定义蛇的数据结构 int length; //蛇长度 int[] snakeX = new int[600]; // 蛇的 x 坐标 int[] snakeY = new int[500]; // 蛇的 y 坐标 String fx; // 方向 // 食物坐标 int foodx; int foody; Random random = new Random(); int score; //游戏当前状态 boolean isStart = false; //默认是暂停状态 boolean isFail = false; //游戏失败 // 定时器 --- 100 ms 执行一次 Timer timer = new Timer(100,this); public GamePanel(){ init(); // 获得焦点和键盘事件 this.setFocusable(true); //获得焦点 this.addKeyListener(this); //获得键盘监听事件 timer.start(); //定时器启动 score = 10; } //初始化 public void init(){ length = 3; snakeX[0] = 100;snakeY[0] = 100; snakeX[1] = 75;snakeY[1] = 100; snakeX[2] = 50;snakeY[2] = 100; fx = "R"; foodx = 25 + 25*random.nextInt(34); foody = 75 + 25*random.nextInt(24); } // 绘制面板,游戏中的所有东西都是用这个画笔 @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 绘制静态面板 this.setBackground(Color.WHITE); Data.header.paintIcon(this,g,25,11); g.fillRect(25,75,850,600); //默认游戏界面 // 画小蛇的食物 Data.food.paintIcon(this,g,foodx,foody); // 画积分 g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,18)); g.drawString("长度"+length,750,35); g.drawString("分数"+score,750,54); // 把小蛇画上去,初始化向右 if(fx.equals("R")){ Data.right.paintIcon(this,g,snakeX[0],snakeY[0]); } else if(fx.equals("L")){ Data.left.paintIcon(this,g,snakeX[0],snakeY[0]); }else if(fx.equals("U")){ Data.up.paintIcon(this,g,snakeX[0],snakeY[0]); } else if(fx.equals("D")){ Data.down.paintIcon(this,g,snakeX[0],snakeY[0]); } // 动态增加身体 for(int i= 1;i < length;++i){ Data.body.paintIcon(this,g,snakeX[i],snakeY[i]); } //游戏状态 if(isStart == false){ g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,40)); g.drawString("按下空格开始游戏",300,300); } if(isFail){ g.setColor(Color.red); g.setFont(new Font("微软雅黑",Font.BOLD,40)); g.drawString("游戏失败,按下空格重新开始!",200,300); } } //键盘监听事件 @Override public void keyPressed(KeyEvent e) { //获得键盘按键 int keyCode = e.getKeyCode(); if(keyCode == KeyEvent.VK_SPACE){ if(isFail){ //游戏失败 //重新开始 isFail = false; init(); //初始化 } else{ isStart = !isStart; } repaint(); } // 小蛇移动 if(keyCode == KeyEvent.VK_LEFT){ fx = "L"; }else if(keyCode == KeyEvent.VK_RIGHT){ fx = "R"; }else if(keyCode == KeyEvent.VK_UP){ fx = "U"; }else if(keyCode == KeyEvent.VK_DOWN){ fx = "D"; } } // 事件监听----定时器--通过固定的时间刷新 @Override public void actionPerformed(ActionEvent e) { if(isStart && isFail == false){ // 游戏开始,小蛇动起来 // 吃食物 if(snakeX[0] == foodx && snakeY[0] == foody){ length+=1; score+=10; //再次随机生成食物 foodx = 25 + 25*random.nextInt(34); foody = 75 + 25*random.nextInt(24); } // 右移 ,后一节移到前一节 for(int i = length-1;i>0;i--){ snakeX[i] = snakeX[i-1]; snakeY[i] = snakeY[i-1]; } // 走向 if(fx.equals("R")){ snakeX[0] = snakeX[0]+25; if(snakeX[0] > 850){ snakeX[0] = 25; } }else if(fx.equals("L")){ snakeX[0] = snakeX[0]-25; if(snakeX[0] < 25){ snakeX[0] = 850; } } else if(fx.equals("U")){ snakeY[0] = snakeY[0]-25; if(snakeY[0] < 75){ snakeY[0] = 650; } } else if(fx.equals("D")){ snakeY[0] = snakeY[0]+25; if(snakeY[0] > 650){ snakeY[0] = 75; } } // 失败判定,撞到自己 for(int i = 1;i<length;++i){ if(snakeX[0]== snakeX[i] && snakeY[0] == snakeY[i]){ isFail = true; } } repaint(); //重新画一次 } timer.start(); //开始定时器 } @Override public void keyTyped(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } }

游戏的主启动类

package JavaGUI.snake; import javax.swing.*; /** * @Title: StartGame * @Package JavaGUI.snake * @Description: * @author: maze * @date 2020/10/21上午 8:47 */ // 游戏的主启动类 public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setResizable(false); // 窗口大小不可变 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setBounds(10,10,900,750); // 把面板添加到 frame 中 frame.add(new GamePanel()); frame.setVisible(true); } }

五、拓展

把用户信息保存到数据库中,包括上次玩的记录,每次加载的时候先登录用户,验证账号和密码联机登录,比如在界面上有两条蛇一起玩,涉及网络系统界面可以再变的美观一点怎么把这个程序打包成一个 jar 包,让用户点击就可以玩,不用在程序编译器中运行
最新回复(0)