不敢相信,居然用Java写了个“天天酷跑”!

您所在的位置:网站首页 idea鼠标放上去就有解释 不敢相信,居然用Java写了个“天天酷跑”!

不敢相信,居然用Java写了个“天天酷跑”!

2023-04-24 07:45| 来源: 网络整理| 查看: 265

作者 | MyHuey

来源 | https://blog.csdn.net/qq_45909299

首先,写一个需求文档:

一、项目名称:《天天酷跑》(RunDay)

二、功能介绍: 闯关类游戏,玩家登录后,选择进入游戏,通过键盘控制玩家的上下左右移动,来躲避 障碍物和吃金币,玩家躲避的障碍物越多跑酷距离越远,玩家吃的金币越多,得分越高。

三、功能模块: 

1、登录界面 

用户名(输入框,明文) 密码(输入框,密文) 登录、取消按钮 

2、菜单选择界面 

开始游戏按钮(图片按钮) 帮助按钮 退出按钮 

3、缓冲加载界面 

自动加载进度条,加载完毕之后,跳转到下一界面 

4、游戏主界面 

移动的背景图片、动态的玩家、五种障碍物持续出现、玩家和障碍物的碰撞、 暂停、继续功能、玩家的移动功能 

5、结束界面 

获取玩家的得分、跑酷距离。继续游戏、返回主菜单的功能。

四、开发者:Huey

五、版本号:1.0

六、开发时间:2020.11.16

开发模式:MVC模式

M:Model(数据层),存储的是实体类。

V:View(显示层),存储的是关于界面的类。

C:Controller(控制层),存储的是相关的逻辑层代码。

企业级项目命名规范:

cn.sqc.runday.view

(一):登录界面界面功能需求图如下:

接下来我们再做一些准备工作:导入相关图片素材。

将天天酷跑的图片(Image)资源解压到桌面后,(Image文件如下图所示:)

复制到Eclipse中,单击src,直接Ctrl+V。

本文将实现cn.sqc.runday.view这一界面内容。

相关代码如下:

package cn.sqc.runday.view; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; /**  *   * @author Huey  * @date 2020-11-16  * 登录界面:用户名输入框  密码输入框  登录取消按钮 功能  *  */ public class LoginFrame extends JFrame{  //用户名变量(文本)  JLabel userLabel;  //用户名输入框(文本输入框)  JTextField userField;  //密码变量(文本)  JLabel userLabel2;  //密码输入框(文本输入框)  JPasswordField userField2;  //登录按钮、取消按钮(按钮)  JButton Login,Cancel;  public LoginFrame() {//直接 alt / (无参构造)    userLabel = new JLabel("用户名");    //设置字体   userLabel.setFont(new Font("微软雅黑",Font.BOLD,18));       userLabel2 = new JLabel("密  码");   userLabel2.setFont(new Font("微软雅黑",Font.BOLD,18));       //布局方式:绝对布局   userLabel.setBounds(20, 220, 100, 30);//x位置,y位置,所占显示空间的大小   this.add(userLabel);//将用户名这三个字添加到登录界面上,以下同理   userLabel2.setBounds(20, 280, 100, 30);   this.add(userLabel2);   //用户名输入框   userField = new JTextField();   userField.setBounds(80, 220, 100, 30);   //设置输入框凹陷效果   userField.setBorder(BorderFactory.createLoweredBevelBorder());   //设置输入框背景透明   userField.setOpaque(false);   this.add(userField);      userField2 = new JPasswordField();   userField2.setBounds(80, 280, 100, 30);   userField2.setBorder(BorderFactory.createLoweredBevelBorder());   userField2.setOpaque(false);   this.add(userField2);          //登录按钮   Login = new JButton("登录");   Login.setBounds(45,350,60,36);   //Login.setBackground(new Color(44,22,44));//背景色   //Login.setForeground(Color.BLUE);//前景色     //绑定登录按钮的事件监听   Login.addActionListener(new ActionListener() {//ActionListener alt /        @Override    public void actionPerformed(ActionEvent e) {     //System.out.println("点击登录按钮");     //获取用户名输入框的内容     String userName = userField.getText();     String passWord = userField2.getText();//横杠原因:方法太老了,不推荐用     if("Huey".equals(userName) && "123".equals(passWord)){      //登录成功      JOptionPane.showMessageDialog(null, "欢迎"+userName+"来到天天酷跑游戏");      //跳转到下一界面            //关闭当前界面      dispose();     }else if("".equals(userName) || "".equals(passWord)){      //不能为空      JOptionPane.showMessageDialog(null, "用户名 / 密码不能为空,请重新输入!");     }else{      JOptionPane.showMessageDialog(null, "用户名 / 密码输入错误,请重新输入!");     }         }   });   this.add(Login);    //取消按钮   Cancel = new JButton("取消");   Cancel.setBounds(135,350,60,36);   this.add(Cancel);   Cancel.addActionListener(new ActionListener() {        @Override    public void actionPerformed(ActionEvent e) {     // TODO Auto-generated method stub     dispose();    }   });         //创建背景面板,并添加到窗体上去   LoginPanel panel = new LoginPanel();   this.add(panel);       //设置登录界面的基本属性   this.setSize(900,530);   this.setLocationRelativeTo(null);//位置居中   this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   this.setUndecorated(true);      //设置窗体的Logo图标   this.setIconImage(new ImageIcon("Image/115.png").getImage());//存储图片   this.setVisible(true);  }        //测试用的main方法       main + Alt /  public static void main(String[] args) {   new LoginFrame();  }  class LoginPanel extends JPanel{//画板   //背景图片变量   Image background;//------ctr shift + o 导包   public LoginPanel() {//-----alt / 回车 构造方法  在{后双击,显示作用域    //读取图片文件,赋值给background变量    try {//-----虽然不大可能,但也做好吃饭噎死的准备     background = ImageIO.read(new File("Image/login.jpg"));//----read参数为File类型    } catch (IOException e) {//-------捕获异常信息     // 打印异常日志信息     e.printStackTrace();    }   }   //绘制方法   @Override   public void paint(Graphics g) {    super.paint(g);    //绘制背景图片    g.drawImage(background, 0, 0,900,530, null);//900,530为宽高   }  }   } //throws ......抛异常,将下面的异常向上抛,交给上级:不建议   为了更清楚地看出代码结构,这里给出部分代码的作用域。

LoginFrame作用域一直到最后一个}

LoginPanel的代码块:

运行结果截图:

1.界面

2.登录

2.1、用户名及密码输入为空的情况:

2.2、用户名或密码输入错误的情况:

2.3、用户名及密码输入正确的情况:

单击弹窗中的“确定”,直接退出。

3.退出

点“取消”即可

(二):开始游戏界面

前文,我们完成了登录界面的搭建。本文将完成开始游戏界面的搭建,并建立起登录界面与开始游戏界面的桥梁。 实现在输对用户名和密码后即可进入开始游戏界面的功能。

界面功能需求图:具体要求:

当鼠标移入开始游戏按钮后,按钮将由暗变亮,鼠标移开后,按钮又由亮变暗。

帮助、离开按钮同理。

另外,当点击离开时,需要实现关闭当前界面的效果。

上代码:package cn.sqc.runday.view; import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import cn.sqc.runday.controller.WindowFrame; public class MainFrame extends JFrame implements MouseListener {  //设置窗体的基本属性 大小  /**   *  1.1、设置窗体基本属性大小 居中 边框隐藏 默认关闭按钮 logo图标   1.2、创建背景面板MainPanel,实现背景图片功能      2.图片按钮功能   */  //2.1创建开始按钮 帮助按钮 离开按钮 组件  JLabel start,help,exit;    JPanel MainPanel;    public MainFrame() {//无参构造,创建对象。并在main函数中调用   //2.2   start = new JLabel(new ImageIcon("Image/hh1.png"));//ImageIcon:图标   start.setBounds(350,320,150,40);   start.setEnabled(false);//false按钮为灰色     start.addMouseListener(this);   this.add(start);      help = new JLabel(new ImageIcon("Image/hh2.png"));   help.setBounds(350,420,150,40);   help.setEnabled(false);   help.addMouseListener(this);   this.add(help);      exit = new JLabel(new ImageIcon("Image/hh3.png"));   exit.setBounds(350, 520, 150, 40);   exit.setEnabled(false);   exit.addMouseListener(this);   this.add(exit);          /**1.实现背景图片及窗体属性*/   MainPanel panel = new MainPanel();   this.add(panel);      //设置窗体基本属性大小 居中 边框隐藏 默认关闭按钮 logo图标   this.setSize(1200,730);//大小   this.setLocationRelativeTo(null);//居中   this.setUndecorated(true);//边框隐藏   this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//默认关闭   this.setIconImage(new ImageIcon("Image/115.png").getImage());//logo   this.setVisible(true);     }    public static void main(String[] args) {   new MainFrame();  }    //2、创建背景面板MainPanel,实现背景图片功能  class MainPanel extends JPanel{//创建的MainPanel类,在MainFrame中调用  Image background;    public MainPanel() {   try {    background = ImageIO.read(new File("Image/main.png"));   } catch (IOException e) {    e.printStackTrace();   }  }  @Override  public void paint(Graphics g) {   super.paint(g);   g.drawImage(background, 0, 0,1200,730, null);   }  }     //以下五个方法均为添加 implements MouseListener 后,快捷出来的  @Override  public void mouseClicked(MouseEvent e) {   //鼠标点击   if(e.getSource().equals(start)){    //跳转到下一界面    new WindowFrame().Start();    //关闭当前界面     //dispose();   }else if(e.getSource().equals(exit)){    dispose();   }else if(e.getSource().equals(help)){    JOptionPane.showMessageDialog(null, "有疑问请联系开发者:Huey");   }     }  @Override  public void mousePressed(MouseEvent e) {   // TODO Auto-generated method stub     }  @Override  public void mouseReleased(MouseEvent e) {   // TODO Auto-generated method stub     }  @Override  public void mouseEntered(MouseEvent e) {   // 鼠标移入   if(e.getSource().equals(start)){//e指一个事件。e.getSource()获取事件    //如果鼠标移入到(start)组件(图片按钮)    start.setEnabled(true);   }else if(e.getSource().equals(help)){    help.setEnabled(true);   }else if(e.getSource().equals(exit)){    exit.setEnabled(true);   }  }  @Override  public void mouseExited(MouseEvent e) {   //鼠标移出    if(e.getSource().equals(start)){     start.setEnabled(false);   }else if(e.getSource().equals(help)){    help.setEnabled(false);   }else if(e.getSource().equals(exit)){    exit.setEnabled(false);   }  } }测试:

先填补上文的缺憾,加上new MainFrame();语句。调用我们刚刚写好的开始游戏界面。

登录界面:

单击确定

完美进入我们写好的登录游戏界面:

现在看开始游戏按钮:

帮助按钮:

点击帮助按钮:

退出按钮:

点击:

大功告成!

(三):缓冲加载游戏界面

前文,我们完成了开始游戏界面的搭建。本文将实现缓冲加载界面的搭建。并搭建与前面俩界面间的桥梁。 实现输入正确用户名密码后,进入开始游戏界面,点击开始游戏按钮后,进入缓冲加载界面的功能。

界面示意图:具体要求:缓存加载界面:背景图片、进度条动态加载过程。(线程)我们想要实现动态的缓冲加载过程,让进度条动起来,就需要引入线程的概念了。线程:

Thread类中这样定义:

线程是程序中执行的线程,Java虚拟机允许程序同时运行多个执行线程。

举个例子,你用百度网盘下载一部电影,这就是一个线程。而如果你同时下载多部电影,这就是多线程了。

1.线程有6种状态:新建,运行,阻塞,等待,计时等待和终止。

新建:当使用new操作符创建新线程时,线程处于“新建”状态。 运行(可运行):调用start()方法。 阻塞:当线程需要获得对象的内置锁,而该锁正在被其他线程拥有。 等待:当线程等待其他线程通知调度表可以运行时。 计时等待:对于一些含有时间参数的方法,如Thread类的sleep() 。 终止:当run()方法运行完毕或出现异常时。

2.创建线程的两种方式:

1、实现Runnable 2、实现Thread类

直接上代码:

package cn.sqc.runday.controller; import java.awt.BorderLayout; import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JProgressBar; /**  *   * @author Huey  * @date 2020-11-18  * 缓存加载界面:背景图片、进度条  * 动态加载过程。(线程)  *   */ public class WindowFrame extends JFrame implements Runnable{  JLabel background;  //进度条  JProgressBar jdt;    //创建一个线程并启动  public void Start(){   WindowFrame frame = new WindowFrame();   Thread t = new Thread(frame);//t代表线程   //启动线程   t.start();   dispose();  }      public WindowFrame() {   background = new JLabel(new ImageIcon("Image/hbg.jpg"));   this.add(BorderLayout.NORTH,background);//放在窗口上面      jdt = new JProgressBar();   jdt.setStringPainted(true);//加载以字符串形式呈现出来。0%   jdt.setBackground(Color.ORANGE);   this.add(BorderLayout.SOUTH,jdt);      //大小 568 * 340   this.setSize(568,340);   this.setLocationRelativeTo(null);   this.setDefaultCloseOperation(3);   this.setUndecorated(true);   this.setIconImage(new ImageIcon("Image/115.png").getImage());    this.setVisible(true);   }      public static void main(String[] args) {   new WindowFrame().Start();  }    @Override  public void run() {   //启动线程后,线程具体执行的内容   int [] values = {0,1,3,10,23,32,40,47,55,66,76,86,89,95,99,99,99,100};   for(int i=0; i=580){// 下落归下落,也得温柔点,不能让小人儿踩破了地板    y = 580;   }  }  //玩家移动的方法  public void step(){   //玩家图片的切换   image = images[index ++ /3%images.length];   //玩家坐标改变(玩家坐标通过键盘控制,此次不做处理)  }  //绘制玩家的方法  public void paintPerson(Graphics g){   g.drawImage(image, x, y, WIDTH, HEIGHT, null);  }  //判断玩家是否越界的方法  public boolean outOfBounds(){   return this.x >= GameFrame.WIDTH || this.x 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3