GUI练习:贪吃蛇游戏
GUI练习:贪吃蛇游戏
- 帧:如果时间片足够小,就是动画
- 键盘监听
- 定时器Timer
- 代码按照
B站狂神说视频教程编写,有改动:不能回头,初始位置随机,把计算坐标作为单独的方法提出来,食物位置不能和蛇重合 - 图片素材:https://ws28.cn/f/4gkrkyf5bm4
-
StartGame.java 主启动类
//游戏的主启动类 public class StartGame { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setBounds(210,210,900,720); frame.setResizable(false);//窗口大小不可变 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //正常游戏界面都应该在面板上 frame.add(new GamePanel()); frame.setVisible(true); } } -
Data.java 数据类
//数据中心 public class Data { //相对路径 a.jpg //绝对路径 / 相当于当前的项目 private static URL headerURL = Data.class.getResource("statics/header.png"); public static ImageIcon header = new ImageIcon(headerURL); private static URL upURL = Data.class.getResource("statics/up.png"); private static URL downURL = Data.class.getResource("statics/down.png"); private static URL leftURL = Data.class.getResource("statics/left.png"); private static URL rightURL = Data.class.getResource("statics/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); private static URL bodyURL = Data.class.getResource("statics/body.png"); public static ImageIcon body = new ImageIcon(bodyURL); private static URL foodURL = Data.class.getResource("statics/food.png"); public static ImageIcon food = new ImageIcon(foodURL); } -
GamePanel.java 游戏面板
//游戏的面板 public class GamePanel extends JPanel implements KeyListener, ActionListener { //画布左上角坐标 public static final int firstX=25; public static final int firstY=75; public static final int size=25;//格子大小 共34*24个格子 //随机数 public static Random n=new Random(); //定义蛇的数据结构 int length;//蛇的长度 int[] snakeX=new int[900];//蛇的x坐标 25*25 int[] snakeY=new int[900];//蛇的y坐标 25*25 char fx;//初始方向 //食物坐标 int foodx; int foody; int score;//成绩 Random random = new Random(); boolean isStart=false;//游戏当前状态,默认不开始 boolean isFail=false;//游戏失败 //定时器 Timer timer = new Timer(200,this);//100毫秒刷新一次 //构造方法 public GamePanel(){ init(); //获得焦点和键盘事件 this.setFocusable(true);//获得焦点事件 this.addKeyListener(this);//获得键盘监听事件 timer.start();//游戏一开始就启动 } //初始化方法 public void init(){ score=0; length=3; //(int) (Math.random() * (y + 1 - x)) + x 随机取 [x,y] 区间整数 int head_x = (int) (Math.random() * (31 + 1 - 3)) + 3; int head_y = (int) (Math.random() * (21 + 1 - 3)) + 3; snakeX[0]=setX(head_x);snakeY[0]=setY(head_y);//脑袋的坐标 snakeX[1]=snakeX[0]-size;snakeY[1]=snakeY[0];//脑袋的坐标 snakeX[2]=snakeX[0]-size*2;snakeY[2]=snakeY[0];//脑袋的坐标 fx='R'; foodx=setX(random.nextInt(34)+1); foody=setY(random.nextInt(24)+1); for (int i = 0; i < length; i++) { while (foodx == snakeX[i] && foody == snakeY[i]) { foodx=setX(random.nextInt(34)+1); foody=setY(random.nextInt(24)+1); } } } //绘制面板,游戏中的所有东西,都使用这个画笔画 @Override protected void paintComponent(Graphics g) { super.paintComponent(g);//清屏的作用,删掉会闪屏 //绘制静态的面板 this.setBackground(Color.WHITE); Data.header.paintIcon(this,g,25,11);//头部广告栏 g.setColor(Color.PINK); g.fillRect(25,75,850,600);//默认的游戏界面 g.setColor(Color.BLACK); //画成绩 g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,18)); g.drawString("长度:"+length,750,33); g.drawString("分数:"+score,750,50); //画食物 Data.food.paintIcon(this,g,foodx,foody); //把蛇画上去 for (int i = 1; i < length; i++) {//画身体 Data.body.paintIcon(this,g,snakeX[i],snakeY[i]); } switch (fx){//画蛇头 case 'R': Data.right.paintIcon(this,g,snakeX[0],snakeY[0]); break; case 'L': Data.left.paintIcon(this,g,snakeX[0],snakeY[0]); break; case 'U': Data.up.paintIcon(this,g,snakeX[0],snakeY[0]); break; case 'D': Data.down.paintIcon(this,g,snakeX[0],snakeY[0]); break; } //游戏状态 if (!isStart) { g.setColor(Color.white); g.setFont(new Font("微软雅黑",Font.BOLD,60)); g.drawString("按下空格开始游戏",210,360); } if(isFail){ g.setColor(Color.red); g.setFont(new Font("微软雅黑",Font.BOLD,60)); g.drawString("失败!按下空格重新开始",140,360); } } //键盘监听器 @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_UP) { if (fx=='D') fx='D'; else fx='U'; }else if (keyCode == KeyEvent.VK_DOWN){ if (fx=='U') fx='U'; else fx='D'; }else if (keyCode == KeyEvent.VK_LEFT){ if (fx=='R') fx='R'; else fx='L'; }else if (keyCode == KeyEvent.VK_RIGHT){ if (fx=='L') fx='L'; else fx='R'; } } //事件监听--需要通过固定时间来刷新 1s-10次 @Override public void actionPerformed(ActionEvent e) { if (isStart && (!isFail)) { //吃食物 if (snakeX[0] == foodx && snakeY[0] == foody) { foodx=setX(random.nextInt(34)+1); foody=setY(random.nextInt(24)+1); length++; score+=10; } //身体移动 for (int i = length-1; i > 0; i--) { snakeX[i]=snakeX[i-1]; snakeY[i]=snakeY[i-1]; } //走向 if (fx == 'R') { snakeX[0]+=size; if (snakeX[0] > setX(34)) snakeX[0] = setX(1); } else if (fx == 'L') { snakeX[0]-=size; if (snakeX[0] < setX(1)) snakeX[0] = setX(34); }else if (fx == 'U') { snakeY[0]-=size; if (snakeY[0] < setY(1)) snakeY[0] = setY(24); }else if (fx == 'D') { snakeY[0]+=size; if (snakeY[0] > setY(24)) snakeY[0] = setY(1); } //失败判断,撞到自己 for (int i = 1; i < length; i++) { if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]) { isFail = true; } } repaint(); } timer.start(); } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } //计算坐标 public int setX(int i){//参数为实际坐标,不是数组下标 return firstX+(i-1)*size; } public int setY(int i){ return firstY+(i-1)*size; } }

浙公网安备 33010602011771号