COCOS 微信小游戏开发完整记录和坑

4,569

COCOS微信小游戏开发完整记录 -> 结尾有惊喜

背景

因为我个人喜欢游戏,一直想做一小游戏,但是一直拖着,没时间做,现在终于在周末空闲时间做了一个微信小游戏。

第一次写技术文章,篇幅可能较长,但是自我感觉干货满满,如果有不好的地方希望小伙伴们多多提出意见,内含游戏核心数值设计的全过程。

如果你正准备做游戏开发,或者不知道怎么下手,希望本文能为你带来一定的收获

image.png

废话不多说,先上图看看效果,如果想先体验,可直接拖到底部

1411623937312_.pic.jpg

1421623937312_.pic.jpg

目录

  • 游戏玩法介绍
  • 数值设计(砖块血量,玩家攻击,攻速等关系)
  • 开发过程
  • 采坑记录
  • 微信部署相关问题
  • 微信广告接入

注意:本文不涉及太多具体代码以及全部代码,会列出一个新手在 Cocos 开发一款完整游戏的思想,避免大家采坑,但是会有一些核心的数值或者关键代码提供参考学习,纯干货。

1 游戏基本玩法介绍

当时最初的设计是一款轻量级的射击爽游,自动发射子弹,通过手指触摸移动来改变角色的移动,吃不同的 Buff 可以叠加对应的能力,通过打击砖块获得更高分数。

以下是目前支持的一些功能

  • 自动发射子弹,双列,三列,四列子弹
  • 飞机移动与砖块碰撞
  • 子弹碰撞
  • 完整排行榜实现
  • 完整游戏流程,开始,游戏中,游戏结束
  • 砖块血量数值算法
  • Buff 叠加,攻击,攻速,炮筒数量,无敌 Buff

2 数值设计

如果条件允许数值设计其实也是专门的数值策划的工作,但是... 我也做了,为了想要得到玩家在不同时间段攻击应该是多少,我做了一个 Excel 来推算玩家攻击的数值,后作为实际开发怪物生命的设置。先上一张我的数值设计的样子(实际上 Excel 推算了 100 行的数值左右,图太长,所以我只截取了前面一部分)。

数值设计我觉得算是整个游戏的一个核心,是游戏平衡,可玩性的核心,这一部分我花了一部分时间来思考,整个游戏设计是只有攻击和生命,没有护甲,所以对于计算来说用了比较简单的 减法公式

公式1:攻击 = 消耗

公式2:生命 - 消耗 = 结果

QQ20210705-164023.png

数值组成字段 Tab 说明

  • 怪物波数:砖块是一波一波的下落(一波砖块为一排)
  • 打击时间:平均打死一个怪物的时间
  • 成长率:打击的时间成长率(控制打击的时间因素)
  • 怪物血量:砖块的生命值
  • 血量成长:控制怪物血量的成长因素
  • 玩家攻击:最终得出不同波数怪物玩家攻击数值应该是多少

数值设计过程

对于 Excel 的操作我就不做介绍了,各位大佬自行百度。应该各种教程特别多

1:我的想法就是 最初玩家一秒能打死一个砖块(因为初始的攻击速度在 0.5 秒一发子弹,子弹移动到怪物身上大约0.5 秒左右),于是就有了第二列第一行 打击时间为 1s

得出第一个初始值:打击时间 1s

2:然后就是每波怪,玩家的打击时间应该增加多少呢?因为这是一个怪物无限往下掉,打击时间肯定不能太久,否则打不死就 GG 了,所以我设定了一个成长率为 0.01,通过数值验证比较合适,到第30波的时候也就 1.3s,

得到第二个初始值以及计算公式:打击时间成长率 0.01,打击时间的计算公式为: =B2+B2*C2 【注意:这个值需要多次尝试,根据自己的需求来得到最终的结果】

image.png

3:然后就是怪物的血量应该是多少,一开始肯定不能设计得太多,如果设计得太多,并且要在 1 秒内打死 那么攻击肯定也特别高,而我的想法就是攻击需要根据吃 Buff 来进行叠加。

得出第三个初始值:怪物初始血量为 2

4:同样的血量肯定有成长因素,所以这里就出现了一个血量成长率,这里我最开始从 1 的倍率一直到 0.2 倍率都试了,发现 0.55 比较合适成长不低不高,算是比较满意的状态

得到第四个初始值以及实际血量计算公式:血量成长率 0.55, 血量成长的计算公式为: =A3A3E2+D2*E2,血量增加除了和成长有关,还得和砖块的波数成比例,波数越高怪物血量随之约高。

怪物波数的平方*血量成长 + 上一波砖块血量 * 血量成长,【最开始我只想了 血量 * 成长,发现比较低,在50波以上的时候数值还是太低了,所以我增加了一个怪物波数的条件】

image.png

5:最后一个 玩家攻击就相对比较简单了,砖块血量 / 打击时间 = 玩家攻击

得出玩家攻击数值:初始值设定的 2 (因为怪物设定的初始血量为 2,因为一发打死一个小朋友) 玩家实际攻击 = 砖块血量 / 打击时间

image.png

至此整个游戏核心的数值就设计完毕,但是漏了一点,因为这是一个类似射击类的游戏,子弹不止一发,所以后面需要 将子弹速度、炮筒数量加进去一起计算

以下是砖块血量计算的完整代码

image.png

第一行 hp 变量最终值乘以了 0.65,因为 Buff 的随机性导致攻击可能不能和数值表设计的完全一致,所以这里做了一个优化。

当炮筒达到满状态并且攻速达到满状态的时候(满攻速是 2 帧(≈0.03s)一发,算上满炮筒 大概是 0.03s 3 or 4发子弹),当时发现攻击过于高了,所以在玩家达到不同状态的时候给 HP 增加了一定的数值修正。

攻速 Buff 每次减少 3 帧(也就是攻速会提升 0.045s 左右),上限为 2 帧。

攻击 Buff 每次增加 3 点攻击力,无上限,出现的概率比攻速要大

3 开发过程

游戏核心数值搞定了,开发其实就是比较轻松的了,无非查查API,想想游戏怎么做。

这里我列一下我做整个游戏的一个步骤

1:想好整个游戏的具体玩法,如何操作,如果胜利和死亡,核心玩法是什么。一步一步的完成整个游戏。

2:第一步,完成玩家的操作,拖拽移动

3:第二步,完成玩家的发射等功能、子弹管理(速度、子弹状态、炮筒数量等等)。

4:第三步:开始制作砖块,设定好砖块的位置,按照固定的速度往下掉。

5:第四步:处理子弹和砖块的碰撞【这里自喷一下,最开始我居然用的 Cocos 提供的物理引擎来进行碰撞检测等操作,后发现当子弹特别多的时候,就有点卡了,于是我查了一下,找到了普通的 2d 碰撞检测】。

6:第五步:制作各种界面,如开始界面,结束界面等。

哦对了,游戏涉及到的数据存储,我是用的 Node 来写的后端,因为作为前端开发,只会 Node 哈哈哈

4 采坑记录

  • 坑1 :UI 同学给了我一版新的 UI 图,我换上之后发现在 IOS 平台(微信小游戏)无法加载这个图(因为这个图不起眼,我就没有注意),安卓所有平台 小游戏 无法打开小程序,各种百度,以及微信开放社区都无法查阅相关信息, 偶然间我看到有人说,小游戏的图片尺寸不能超过 2048, 于是我检测了一下我的图片,确实哪一张图超过了2048,于是我试了一下,结果我特 &……*&%%¥&, 搞了我几天的问题,竟然是这 。。。

image.png

  • 坑2 :精灵图,对于 Cocos 建议不用自己去合并精灵图,麻烦,而且不易扩展,每次新增一个图都要重新生成。可以使用官方提供的 自动合并精灵图,会根据我们的引用自动生成精灵图,特别好用

  • 坑3 :我在引入友盟统计的时候,发现导入进来各种问题,微信授权也没有,然后我发现不知是我操作问题,还是 SDK 代码的问题,于是我自己吧友盟的 min.js 文件格式化之后 一通改动。

额其他的暂时没想到了,如果想到了,我在在补上。

5 微信部署相关问题

1:微信部署其实很简单,微信小游戏现在不需要软著了,但是貌似隔壁抖音必须要软著

2:目前提审的时候 基本上都是一次过,只要不涉及什么违法违纪什么的,基本上都没问题。

3:值得一提的是,微信小程序做版本兼容一直是个很头疼的问题,这个得想好

Cocos 提供了全局参数 CC_DEBUG 为true表示开发环境

小程序提供了 __wxConfig.envVersion 属性用来区分小程序的状态 develop = 开发版 ,trial = 体验版, release = 正式版

6 微信广告接入

1: 这个也很简单,但是前提是 需要满足 1000 独立 UV ,这个比较麻烦,但是没有什么是难道我们强大的国家(伟大、光荣、正确的中国共产党万岁!伟大、光荣、英雄的中国人民万岁!

2:然后有个小问题就是,微信 Banner 广告如何正确的定位在底部,因为微信是按照他自己的位置和像素进行计算,而且只支持top属性,所以很坑爹,也就是说和 Cocos 的尺寸并不兼容,这里我说一下我的解决方案。

// 定位 Left 的计算方式
Left = (屏幕宽 - 设定的 Banner 宽) / 2;

// 定位 Top 的计算方式,这里的 20 是自己设定的距离底部的距离,Banner的高度需要通过 onResize事件来动态获取
Top = 屏幕高 - Banner 高 - 20;

以下是详细的相关代码

const getWxSystemInfo = () => {
    return new Promise(resolve => {
        wxFn().getSystemInfo({
            success: res => {
                resolve(res);
            }
        })
    })
}


/**
* 下面的内容在一个函数体内,我单独复制出来的
**/
const wxInfo: any = await getWxSystemInfo();
        
// 首页banner
this.homeBannerAd = wxFn().createBannerAd({
    adUnitId: 'adUnitId',
    adIntervals: 30,
    style: {
        left: 20,
        // 初始化的时候 随便设
        top: 0, 
        width: wxInfo.screenWidth - 40
    }
});
this.homeBannerAd?.onResize((res) => {
    this.homeBannerAd.style.top = wxInfo.screenHeight - res.height - 20;
});

终于,写完了,,

image.png

惊喜

现在这个游戏第一期排名送现金红包活动,大家可以去体验玩玩,顺便赚钱钱 😄 😄 😄

以下是体验地址,欢迎大家体验

gh_7189d0e0ae6d_258.jpg

如果大家有什么问题,或者不清楚的欢迎留言讨论!!!

最后感谢 UI 大佬提供的资源素材

他的虎课网:huke88.com/person/opus…

他的站酷:zhujiu.zcool.com.cn/