1 Star 5 Fork 86

oOLzYOo / cocos-framework

forked from LiamYip / cocos-framework 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

Cocos Framework

frok from liamyip,原项目地址为:https://gitee.com/liamyip/cocos-framework

用以学习,并展示一些自己的小demo。

目录

前言

这套框架是我个人开发过程中的积累,已应用于我个人的几个小项目中。单scene多prefab形式,轻量,各个功能基本都可单独拆解开使用。

演示

部分功能演示地址 https://leeyip.github.io/cocos-framework/

框架结构

动画状态机

文件路径(scripts/animator/)

详见 https://github.com/LeeYip/cocos-animator

全局时间管理器

文件路径(scripts/common/cmpt/base/Timer.ts)

组件在场景加载后会自动绑定常驻节点,由timeScale控制每帧间隔时间的缩放。引入并修改了开源库tween.js,在Timer组件中更新和控制,使用方式请参考 https://github.com/tweenjs/tween.js

关于我对tween.js的修改

  1. 设置了新的Group,用以执行受timeScale影响的tween动画
// 执行tween,让node用1000毫秒x坐标移动到100处
new Tween(node)
    .to({x: 100}, 1000)
    .start();

// 执行tween,让node用1000毫秒x坐标移动到100处,实际动画运行时间受timeScale影响
new Tween(node, SCALE_TWEEN)
    .to({x: 100}, 1000)
    .start();
  1. 加入了新的接口bindCCObject(obj: cc.Object),可以将tween与cc.Node或cc.Component等类型为cc.Object的对象进行绑定。当Node或Component被销毁时,与之绑定的tween也会自动销毁。
// 比如构造参数使用cc.Node
let node: cc.Node;
let tween = new Tween(node)
    .to({x: 100}, 1000)
    .start();
// node销毁后,不需要手动销毁tween,框架内部会自动销毁
node.destory();


// 或者主动绑定一个cc.Object类型的对象
let comp: cc.Component;
let tween = new Tween({a: 1})
    .to({a: 10}, 1000)
    .start()
    .bindCCObject(comp);
// 当comp销毁后,同样tween也会自动销毁
comp.destory();
  • 属性
    • timeScale: number dt缩放倍数,1为正常速度,0为暂停。修改时触发时间缩放值修改事件
    • realDt: number 距上一帧间隔的真实时间
    • scaleDt: number 距上一帧间隔经过timeScale缩放的时间
  • 方法
    • reset() 重置timeScale,触发timeScale事件
    • gamePause() 暂停游戏 timeScale设置为0,触发暂停事件
    • gameResume() 恢复游戏 timeScale恢复为暂停前的值,触发恢复事件

全局层级管理

文件路径(scripts/common/cmpt/base/Layer.ts)

组件需要绑在场景的根节点或者常驻节点上,所需的节点层级结构参照项目工程内的Main场景

// 弹窗组件需要继承DialogBase,并重写open方法和close方法,用来处理弹窗打开和关闭时的逻辑
export default class DlgExample extends DialogBase {
    public static pUrl: string = "example/DlgExample";

    /**
     * @override
     */
    public open(num1: number, num2: number) {
        // do something...
    }

    /**
     * @override
     */
    public close() {
        super.close();
        // do something...
    }
}

打开一个弹窗,并传递open方法的参数,弹窗prefab路径填写相对于resources/prefab/dialog/下的路径

// 建议在弹窗组件类上加一个静态属性pUrl用以标明路径,这样在代码里便于查找和跳转引用
Layer.inst.openUniDialog(DlgExample.pUrl, 1, 2);
// 如果不喜欢上面的方式,也可直接填写路径
Layer.inst.openUniDialog("example/DlgExample", 1, 2);

可异步等待某个弹窗关闭

await Layer.inst.waitCloseDialog(DlgExample.pUrl);
// 当在某处关闭了DlgExample这个弹窗或当前不存在此弹窗时,才会往下执行
// do something...
  • 方法
    • enterHome(): Promise<cc.Node> 进入主界面
    • enterGame(): Promise<cc.Node> 进入游戏界面
    • getDialog(url: string): DialogBase 获取弹窗组件(返回遍历到的第一个)
    • openDialog(url: string, ...args: any[]) (同步方法,需确保事先已加载预制资源)打开弹窗
    • openUniDialog(url: string, ...args: any[]) (同步方法,需确保事先已加载预制资源)打开唯一弹窗,同一弹窗只能同时存在一个
    • openDialogAsync(url: string, ...args: any[]): Promise<void> (异步方法)打开弹窗
    • openUniDialogAsync(url: string, ...args: any[]): Promise<void> (异步方法)打开唯一弹窗,同一弹窗节点只能同时存在一个
    • closeDialog(url: string, play: boolean = false) 关闭遍历到的第一个弹窗
    • closeDialogs(url: string = "", play: boolean = false) 关闭所有同路径弹窗,不传参则关闭所有弹窗
    • waitCloseDialog(url: string): Promise<void> 异步等待弹窗关闭(只等待遍历到的第一个)
    • waitCloseDialogs(url: string): Promise<void> 异步等待所有同路径弹窗关闭
    • showTip(data: TipData | string) 弹出一条文字提示
    • clearTips() 清空所有提示
    • showLoading() 打开全局loading遮罩(打开与关闭的调用必须一一对应)
    • hideLoading() 关闭全局loading遮罩

全局事件管理器

文件路径(scripts/common/util/Events.ts)

全局事件管理,装饰器风格简化事件注册注销,支持异步等待事件监听函数的结束

export default class Test extends cc.Component {
    protected onLoad() {
        // 注册当前类使用preloadEvent装饰器绑定的所有事件
        Events.targetOn(this);
    }

    protected onDestroy() {
        // 注销此对象上绑定的所有事件
        Events.targetOff(this);
    }

    // 使用装饰器绑定对应事件监听的函数
    @preloadEvent(EventName.GAME_PAUSE)
    private eventGamePause() {
        
    }

    @preloadEvent(EventName.GAME_RESUME)
    private eventGameResume() {
        
    }

    // 若装饰器第二个参数传true,则触发一次监听函数后会自动注销事件
    @preloadEvent(EventName.TIME_SCALE, true)
    private eventTimeScale() {
        
    }
}

或者也可使用类装饰器覆盖onLoad中和onDestroy方法,并分别在其中调用targetOn与targetOff

// 参数为true则会注册父类用preloadEvent绑定的事件
// 参数为false则只注册当前类用preloadEvent绑定的事件
@eventsOnLoad(true) // 也可使用@eventsOnEnable,对应于onEnable和onDisable
export default class Test extends cc.Component {
    // 使用装饰器绑定对应事件监听的函数
    @preloadEvent(EventName.GAME_PAUSE)
    private eventGamePause() {
        
    }

    @preloadEvent(EventName.GAME_RESUME)
    private eventGameResume() {
        
    }

    // 若装饰器第二个参数传true,则触发一次监听函数后会自动注销事件
    @preloadEvent(EventName.TIME_SCALE, true)
    private eventTimeScale() {
        
    }
}

当在某处触发事件,对应的监听函数便会被调用,可以给监听函数传参。如果是异步监听函数,也可用await等待所有监听函数执行完毕

    // 发送EventName.GAME_PAUSE事件,并传参
    Events.emit(EventName.GAME_PAUSE, 1, ["2"]);
    // 也可以await等待所有监听函数执行完毕
    await Events.emitAsync(EventName.GAME_PAUSE);
  • 装饰器

    • eventsOnLoad(onSuper: boolean = true) 类装饰器。用于覆盖onLoad和onDestroy方法,在onLoad中注册preloadEvent绑定的所有事件,在onDestroy注销绑定的所有事件
    • eventsOnEnable(onSuper: boolean = true) 类装饰器。用于覆盖onEnable和onDisable方法,在onEnable中注册preloadEvent绑定的所有事件,在onDisable注销绑定的所有事件
    • preloadEvent(event: EventName, once: boolean = false) 非静态成员函数装饰器。用于预先载入待注册的事件,配合eventsOnLoad、eventsOnEnable、targetOn使用
  • 方法

    • targetOn(target: Object, onSuper: boolean = true) 注册与target构造函数预先绑定的所有事件,配合装饰器preloadEvent使用
    • on(event: EventName, cb: (...args: any[]) => void, target: Object, once: boolean = false) 注册事件
    • once(event: EventName, cb: (...args: any[]) => void, target: Object) 注册事件,触发一次后自动注销
    • off(event: EventName, cb: (...args: any[]) => void, target: Object) 移除事件
    • targetOff(target: Object) 移除target上注册的所有事件
    • emit(event: EventName, ...args: any[]) 派发事件
    • emitAsync(event: EventName, ...args: any[]): Promise<void> 派发事件--异步

资源管理器

文件路径(scripts/common/util/Res.ts)

主要是对prefab、图片等进行资源管理,内部自动进行引用计数的加减,使用时需要注意以下要点:

  1. 尽量使用此类的接口加载所有资源、instantiate节点实例,否则需要自行管理引用计数
  2. Res.instantiate不要对动态生成的节点使用,尽量只instantiate prefab上预设好的节点,否则有可能会导致引用计数的管理出错
  3. 调用load接口时如需传入release参数,则同一资源在全局调用load时release参数尽量保持一致,否则可能不符合预期
  4. 请使用ResSpine、ResSprite组件去动态加载spine、图片资源,否则需要自行管理这些资源的引用计数
  • 属性

    • releaseSec: number 资源释放的间隔时间(秒),资源超过此间隔未被load才可释放
  • 方法

    • get<T extends cc.Asset>(url: string, type: typeof cc.Asset): T 获取缓存资源。通常不应直接调用此接口,除非调用前能确保资源已加载并且能自行管理引用计数
    • load<T extends cc.Asset>(url: string, type: typeof cc.Asset, release: boolean = true): Promise<T> 加载resources文件夹下单个资源
    • loadDir<T extends cc.Asset>(url: string, type: typeof cc.Asset, release: boolean = true): Promise<T[]> 加载resources文件夹下某个文件夹内某类资源
    • instantiate(original: cc.Node | cc.Prefab, related?: cc.Node | cc.Prefab): cc.Node 获取节点实例,建立节点与缓存prefab的联系
    • releaseAll() 尝试释放所有缓存资源

音频管理器

文件路径(scripts/common/util/AudioManager.ts)

统一控制bgm和音效的暂停恢复和开关,支持音量渐变播放和渐变停止,支持控制同一音效同时播放的最大数量

  • 属性

    • bgmVolume: number 全局bgm音量
    • sfxVolume: number 全局sfx音量
    • bgmOff: boolean bgm是否关闭
    • sfxOff: boolean sfx是否关闭
    • bgmPause: boolean bgm是否暂停
    • sfxPause: boolean sfx是否暂停,暂停时不暂停ui音效
  • 方法

    • playBgm(args: cc.AudioClip | AudioPlayArgs) 播放bgm
    • playSfx(args: cc.AudioClip | AudioPlayArgs, type: SfxType = SfxType.NORMAL) 播放sfx
    • setSfxData(clip: cc.AudioClip, type: SfxType = SfxType.NORMAL, maxNum: number = 8, overStop: boolean = false): SfxData 设置音效数据(用于限制某些短时间内同时大量播放的音效)
    • stopBgm(clip: cc.AudioClip = null, fadeDuration: number = 0) 停止bgm
    • stopSfx(clip: cc.AudioClip = null, type: SfxType = SfxType.NORMAL) 停止sfx
    • stopAll() 停止所有音频
    • pauseAll() 暂停所有音频
    • resumeAll() 恢复所有音频
    • uncacheAll() 停止所有音频,清除所有音频缓存

多语言

文件路径(scripts/i18n/)

支持文字以及图片的多语言切换,不同语言的同一图片需命名一致,配置路径如下,如需更改配置路径请自行更换。详见工程示例

语言表路径:scripts/i18n/config/En.ts和scripts/i18n/config/Zh.ts

图片路径:resources/textures/localizedImage/en/和resources/textures/localizedImage/zh/

如果需要替换字符串中的占位符(形如"%{xxx}"的字符串为占位符),支持以下两种不同的传参形式来获取替换后的字符串

// 语言表 {"test": "test %{arg1} %{arg2} !!!"}
I18n.getText("test", {arg1: "somthing", arg2: 2}); // => "test somthing 2 !!!"
I18n.getText("test", "somthing", 2); // => "test somthing 2 !!!"
  • 属性

    • curLang: LangType 当前语言类型
  • 方法

    • init(language: LangType = LangType.NONE) 初始化语言
    • switch(language: LangType) 切换语言
    • updateLocalizedCmpt() 更新所有多语言组件
    • getKeyByValue(value: string): string 通过语言表value获取对应的key
    • getText(key: string, ...option: [{ [k: string]: string | number }] | Array<string | number>): string 通过key获取语言表中的字符串

一些ui组件

文件路径(scripts/common/cmpt/)

  • VirtualList 虚拟列表,仅生成mask区域内所需的最少节点,且支持节点分层

  • CircleList 无限循环列表/轮播图

  • AnimValue 渐变动画组件基类,可基于此组件实现各种数值渐变动画

    • AnimValueLabel 数字渐变动画组件
    • AnimValueProgress 进度条渐变动画组件
    • AnimValueProgressHP 游戏血条组件
  • 按钮组件

    • ButtonSingle 按钮分组,阻止同一分组内的多个按钮同时点击
    • ButtonChildPos 根据按钮状态改变子节点的坐标
    • ButtonChildGray 根据按钮状态将子节点置灰
  • 资源管理组件,结合资源管理器,自动管理动态加载的资源引用计数

    • ResSpine
    • ResSprite
  • MultiSprite 基于Multi-Texture[1]实现的渲染组件,支持多图集合批,需通过MultiTextureManager管理合批的纹理

    • 兼容web与native
    • 支持Sprite的simple、sliced、tiled、filled渲染类型
    • 支持Cocos自动图集与动态合图的纹理
    • 支持动态修改合批的纹理--MultiTextureManager.setTexture(idx: number, tex: cc.Texture2D)
  • ......

常用工具类

文件路径(scripts/common/util/)

  • Tool 常用工具接口
  • Decorator 装饰器

引擎源码hack

文件路径(scripts/common/hack/)

几个shader

文件路径(res/shader/)

命名规范

  • 文件夹使用小驼峰 files
  • 文件名使用大驼峰 File.ts
  • 类名使用大驼峰 FileClass
  • 属性名、函数名使用小驼峰 func
  • 枚举
enum LangType {
    NONE = "",
    ZH = "zh",
    EN = "en"
}
  • 字符串尽量使用双引号

参考资料

  1. https://forum.cocos.org/t/topic/121618
MIT License Copyright (c) 2021-2022 LeeYip Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

一个基于Cocos Creator的框架 展开 收起
TypeScript
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
TypeScript
1
https://gitee.com/ly790555/cocos-framework.git
git@gitee.com:ly790555/cocos-framework.git
ly790555
cocos-framework
cocos-framework
master

搜索帮助