过年啦!快来领养你的小老虎吧~

1,133 阅读9分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

朋友们可还记得曾经的电子宠物吗,随着最近的科技进步,这类产品已经基本淡出我们的视线了,但是相信曾经的它们还是给您的生活增加了不少的乐趣吧。

虎年马上到了,我带着一点不成熟的想法,做了一个简易版的电子宠物小老虎,希望能给各位掘友的摸鱼时间增加点乐趣。

在电脑上玩,不要在手机上,没做适配

在电脑上玩,不要在手机上,没做适配

在电脑上玩,不要在手机上,没做适配

项目在线体验地址:http://122.112.181.245/

源码地址:gitee.com/wei_rong_xi…

一、玩法介绍

本游戏是对曾经电子宠物的一个模仿,有登录注册,学习说话,吃饺子,串门,等等小游戏,目前是初版,功能较为简单,且本人是后端,前端水平有限,目前的页面比较普通。

目前比较有意思的点在于不同玩家间小老虎的互动,比如去串门,概率偷取其他玩家的饺子,或者去别人家学习一句其他玩家教给小老虎的话。同时可以查看自己的小老虎的饺子被谁偷过等等。

同时宠物设有饥饿值,饥饿值归零后宠物将会离你而去哦。

目前等功能都是通过小老虎说话的方式进行反馈,还比较单一。

下面我们给大家具体介绍下:

1.1 登录

首先是登录界面,不需要注册,只要是不同的账号,自己设置好密码,自动登录并领取一只小老虎。

image.png

1.2 主页面

登录后,进入如下的主页面,映入眼帘的是一直正在喝水的小老虎。

左下角有它的名字:主人的名字 + 的小老虎,建议玩家使用掘金的名字,增加乐趣,还有饥饿值饺子数,其中饥饿值为空后,您的小老虎将会离你而去哦。初始值100,每半小时减1,通过吃饺子可以增加饥饿值。

image.png

下方是四个初始版的功能按钮,分别是过年好,吃饺子,学说话,去串门

上方可以查看谁偷了我的饺子说话记录串门收获

右上方是一个离开按钮。

image.png

1.3 过年好

这个功能是我最初设计的一个最简单的功能,小老虎会说话,会随机从当前老虎学会的话中随机一句,说的是啥,取决于大家教给小老虎的是什么。

image.png

1.4 吃饺子

吃饺子这个主要是为了提升小老虎的饥饿值,每半小时会下降1点,到0后,小老虎就离你而去了哦。只能自己看着曾经玩耍的记录发呆了。

饺子目前我内置了几种,分别对应不同的饥饿值。

玩家可以通过教小老虎说话,或者串门偷取其他玩家获取。

image.png

1.5 学说话

这个功能,是通过玩家在页面输入内容,教给小老虎一些春节祝福的话,或者想说的话。有几率获得随机饺子一枚。

当学的越多,获得饺子的几率就越大了。

image.png

1.6 去串门

去串门,是一个无法确定的功能,会随机取到某个小老虎家里,也会随机的学习一句这个小老虎学会的话,或者是偷取一枚饺子。学说话和偷饺子的比例是4:1,看人品了。

你偷的饺子,都会被这个小老虎记住的哦,不过它目前只能记住最新的15条。

image.png

1.7 谁偷了我的饺子

这里就是查看你的小老虎的饺子都被谁给偷了的地方,会展示偷取的top5,以及最近15条最新的偷取记录。有仇报仇,有怨报怨,被偷的多了,可以去他的掘金文章下面评论,diss他

image.png

1.8 说话记录

这里记录记得小老虎说的一些话,有时候会发现一些比较有趣的事:比如xx的小老虎连饺子都没有xx的小老虎连话都不会说,又或者xx的小老虎离家出走了

image.png

1.9 串门收获

这里可以看你串门的记录,是跟谁学了一句话,还是在谁家偷了一个饺子?

image.png

1.10 离开

这就是一个退出功能,会清除您的登录信息,离开前请记好您的账号密码,账号错了就是新的小老虎了。密码错了可就登不进去报错【Error】了,您的小老虎估计要饿跑了。

二、技术介绍

关于这小老虎,其实没有什么技术难度,都是一些常用的东西。借着掘金的活动,趁着摸鱼的时间,做出来玩一下。

毕竟游戏只是个展现形式,关键还是要学习点有用的。简单聊下比较有意思的点。

2.1 前台

  • vue-admin-template 前台我直接拿以前使用的后台修改的,毕竟我也不是前端,重写估计整不明白。

    使用的是vue admin template, 这个框架是提供给后台管理系统的一套基础vue模板,很不错,前面文章提到的代码生成器生成的vue代码,以及操作页面,都是基于这个的。

    想看代码生成的请传送:juejin.cn/post/705546…

    vue-admin-template源码地址:gitee.com/panjiachen/…

  • 部署

    前台我是放在一台华为云的服务器了,新用户薅羊毛。使用nginx发布的打包好点的dist文件,nginx配置文件如下:

    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log;
    pid /run/nginx.pid;
    
    # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
    include /usr/share/nginx/modules/*.conf;
    
    events {
        worker_connections 1024;
    }
    
    http {
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile            on;
        tcp_nopush          on;
        tcp_nodelay         on;
        keepalive_timeout   65;
        types_hash_max_size 4096;
    
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
    
        # Load modular configuration files from the /etc/nginx/conf.d directory.
        # See http://nginx.org/en/docs/ngx_core_module.html#include
        # for more information.
        include /etc/nginx/conf.d/*.conf;
    
        server {
            listen       80;
            server_name  _;
    
             # gzip config
                gzip on;
                gzip_min_length 1k;
                gzip_comp_level 9;
                gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
                gzip_vary on;
                gzip_disable "MSIE [1-6]\.";
    
            root         /opt/vue/dist;
    
            # Load configuration files for the default server block.
            include /etc/nginx/default.d/*.conf;
    
             location /tiger/ {
                    proxy_pass http://122.112.181.245:9958/;
                    add_header Access-Control-Allow-Origin *; 		
            }
    
                     location /tigerHome/ {
                    proxy_pass http://122.112.181.245/;
                    add_header Access-Control-Allow-Origin *; 		
            }
    
            error_page 404 /404.html;
            location = /404.html {
            }
    
            error_page 500 502 503 504 /50x.html;
            location = /50x.html {
            }
        }
    }
    
    

    有一点需要简单说明下:vue打包js很大,首屏很慢,所以我加了个nginx压缩配置,略微好一些。

2.2 后台

后台代码使用了springboot + mybatis-plus,都是基础的代码。有想看的可以去下载源码,没什么好说的。

mybatis-plus集成传送地址:juejin.cn/post/705472…

数据库使用的mysql8.0.

使用的定时器去扣减小老虎的饥饿值。

有几点重点我可以提一下:

  • 我是用的是hikariCP连接池:

    是目前推荐使用且效率更高的连接池。准确来说是引入mybatis-plus的多数据源依赖,它内部使用的这个连接池。我在前面的springboot集成mybatis-plus当中提过多数据源的事,但是细说,一定要引入如下的配置,否则会报错,我也在mybatis-plus的集成那篇文章补充了:

    spring:
      datasource:
        dynamic:
          hikari:
            max-lifetime: 1800000
            connection-timeout: 5000
            idle-timeout: 3600000
            max-pool-size: 12
            min-idle: 4
            connection-test-query: /**ping*/
    
  • 关于mybatis-plus的lambda语法

    前面的mybatis-plus集成,没有提到关于QueryWrapper的用法,这里我尽量使用其lambda语法来操作,真的是挺方便的,语义很容易让人理解,流式编程让人感到舒适,下面一起感受下:

    List<NianSayLogDO> list = nianSayLogService.lambdaQuery() // 使用lambda查询
            .eq(NianSayLogDO::getNianId, nianId) //where条件,nianId = 参数(nianId)
            .orderByDesc(NianSayLogDO::getCreateTime) // 降序排列,根据create_time
            .last("limit 15") // 在sql最后拼接上 ‘limit 15’,取前15条
            .list(); // 返回一个list
    

    怎么样,是不是简单易懂,爱上了吧。

还有几个有意思的点:

  • 计算学说话获取饺子的概率

    这个地方,让我这个脑子僵硬者转了半天。

    • 首先,我定义了学习说话数量的阶段:

      static {
          wordsNum.add(5);
          wordsNum.add(10);
          wordsNum.add(20);
          wordsNum.add(40);
          wordsNum.add(80);
      }
      
    • 当我查询到当前会说的话的数量后,根据这个wordsNum集合进行比较:

      public static int getChance(int num) {
          // 初始概率是10
          int n = 10;
          // 判断并增加概率数
          n += wordsNum.stream().filter(i -> num > i).mapToInt(i -> 10).sum();
          return n;
      }
      

      看到上面的计算逻辑是不是有点蒙了,意思就是我定义一个初始概率是10;使用java8的流stream,对集合wordsNum中的元素判断,最多判断5次,满足一次条件,就会对初始概率增加10,也就是最高概率是60。

  • 计算获取哪种饺子的概率

    此处我定义了一个枚举:

     /**
      * 饺子枚举
      *
      * @author weirx
      * @date 2022/01/21 11:26
      **/
     public enum DumplingsEnum {
         LEEK_EGG("韭菜鸡蛋饺子", 1, 1),
         PORK_CELERY("猪肉芹菜饺子", 2, 2),
         BEEF("牛肉饺子", 3, 3),
         PORK_ONION("猪肉大葱饺子", 2, 4),
         THREE_FRESH("三鲜饺子", 3, 5),
         SPANISH_MACKEREL("鲅鱼饺子", 2, 6),
         COINS("硬币饺子", 5, 7),
         SUGAR("红糖饺子", 1, 8);
    
         public static DumplingsEnum getOrder(int chance) {
             // 如果只有1个饺子,那么十分之一的概率就是百分之十;
             // 那么8个饺子,十分之一就是八百分之八十
             int i = 80;
             // 百分之10的概率相当于在80个当中选中前8个order(1~8)
             // 百分之20相当于在40个当中选中前8个oder(1~8)
             // 百分之50相当于在16个中选择前8个oder(1~8)
             int i1 = chance / 10;
             int i2 = i / i1;
             int random = RandomUtil.randomInt(1, i2);
             if (random <= 8) {
                 for (DumplingsEnum dumplingsEnum : DumplingsEnum.values()) {
                     if (dumplingsEnum.order == random) {
                         return dumplingsEnum;
                     }
                 }
             }
             return null;
         }
    
         public static void main(String[] args) {
    
         }
    
         private int order;
    
         private String name;
    
         private int hungryNum;
    
         public String getName() {
             return name;
         }
    
         public int getHungryNum() {
             return hungryNum;
         }
    
         DumplingsEnum(String name, int hungryNum, int order) {
             this.name = name;
             this.hungryNum = hungryNum;
             this.order = order;
         }
     }
    

    关于上面根据计算好的概率获取何种饺子的计算过程在上述代码中了,我在注释里没有强行解释,只是通过举例的方式让大家理解吧,我写的时候也是饶了够呛~

    各位用心体会下吧。。。

  • 关于去谁家,偷何种饺子

    这两种的随机方式我都是使用的一种,获取所有的小老虎,然后根据李虎数量随机一个数,根据集合下标获取:

    //获取当前有谁家
    List<NianDO> list = nianService.lambdaQuery().ne(NianDO::getId, nianId).list();
    //随机幸运小伙伴
    int randomInt = list.size() == 1 ? 1 : RandomUtil.randomInt(1, list.size());
    NianDO nianDO = list.get(randomInt - 1);
    

三、总结

上面已经介绍的差不多了,趁着周末和摸鱼时间写了这个东西,发现自从在掘金开始摸鱼后,我连王者都戒掉了,真是太卷了。

希望大家体验的时候多提提建议,我倒是没想到更多有趣的玩法,有些有意思的想法,我可以在春节期间给加上,增加这个小老虎的乐趣。

还有就是我这是在一台华为云的2核4g服务器搭建的,虽然性能够了,但是带宽只有1M,有时候还是会迟钝,谅解~

在电脑上玩,不要在手机上,没做适配

在电脑上玩,不要在手机上,没做适配

在电脑上玩,不要在手机上,没做适配

项目在线体验地址:http://122.112.181.245/

源码地址:gitee.com/wei_rong_xi…