Commit 35a73c2a authored by 张世斌's avatar 张世斌

首次上传

parent 3b680f1f
No preview for this file type
......@@ -2,8 +2,6 @@
cocos creator技术框架下的H5互动模板框架脚手架,基于cocos creator实现快速开发基于绘玩云的H5互动课件。
[视频教程传送门](https://www.bilibili.com/video/BV1Dq4y1t7n5/)
# 使用简介
## 前期准备
......@@ -51,7 +49,21 @@ npm start
```
* 打开浏览器:http://staging-teach.ireadabc.com/template_ci/debug
* [点击查看调试视频教程](https://www.bilibili.com/video/BV1Dq4y1t7n5?p=8)
* 点击右上角齿轮,选择技术选型、调试模式选择“普通”
### 互动模板
* 找到项目根路径下 index.html 文件
* 在引入JS的位置将air.js改为air_online_open.js
* 启动本地服务
```
npm start
```
* 打开浏览器:http://staging-teach.ireadabc.com/template_ci/debug
* 点击右上角齿轮,选择技术选型、调试模式选择“互动”
* 左侧老师、右侧学生
### 真机调试
......@@ -69,11 +81,4 @@ npm start
* 手机和电脑连接同一个Wifi
* 打开调试app,根据提示输入IP地址,点击开始就可以在手机上预览模板了
* 使用 console.log("==调试信息=="); 可以打印日志进行必要的调试
* 点击左上角 “logcat” 可以查看运行日志,(logcat是可以按住拖动的, 所以不用考虑UI遮挡问题)
### 注意事项及常见问题
* 项目里所有文件及文件夹的命名方式要注意不能包含空格、汉字、减号
* 项目里尽量不要使用setTimeout、setInterval等定时器,如果使用了记得在onDestroy中释放掉(onDestroy 是指CocosCreator的生命周期钩子)
* 理论上禁止使用全局变量,因为模板到线上会进行组装,常见问题是一个模板使用多次造成全局变量被读脏
* 使用 this.log("==调试信息=="); 可以打印日志进行必要的调试
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "f0680ae0-c079-45ef-abd7-9e63d90b982b",
"uuid": "d965eb93-2a37-490e-989b-d163f50b6a11",
"downloadMode": 0,
"duration": 0.130612,
"duration": 0.168,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "38b13873-be7b-4f9a-8f74-68d7eb65800d",
"downloadMode": 0,
"duration": 0.20898,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "f8db83d2-5828-4bff-ae64-110f2ab91b6e",
"downloadMode": 0,
"duration": 0.972,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "c5dcb848-8cb1-4a03-9edf-9166bf91ceea",
"downloadMode": 0,
"duration": 10.354813,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "361b2d4a-7d66-4cdb-ac33-0ebc2e1c6aaf",
"downloadMode": 0,
"duration": 9.932,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "26b3ea63-59ba-45eb-982e-a83201422090",
"downloadMode": 0,
"duration": 2.196,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "ceb12779-73c5-4001-82b2-6444cee1292f",
"downloadMode": 0,
"duration": 3.096,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.0.1",
"uuid": "16c77e39-ee05-4f1b-83c2-10ba41022cdf",
"downloadMode": 0,
"duration": 0.731429,
"subMetas": {}
}
\ No newline at end of file
This diff is collapsed.
{
"ver": "1.0.1",
"uuid": "8fb2d623-ea9a-465b-a666-66623353eb18",
"subMetas": {}
}
\ No newline at end of file
{"name":"mao","imagePath":"mao_tex.png","SubTexture":[{"name":"猫01/影子","x":1,"height":66,"y":343,"width":337},{"name":"猫01/尾巴","x":1,"height":109,"y":188,"width":175},{"name":"猫01/右腿","x":178,"height":117,"y":188,"width":104},{"name":"猫01/左腿","x":1,"height":115,"y":569,"width":64},{"name":"猫01/右手","x":427,"height":122,"y":590,"width":69},{"name":"猫01/左手","x":301,"height":74,"y":590,"width":124},{"name":"猫01伸/左手伸直","x":299,"height":169,"y":1,"width":168},{"name":"猫01伸/右手伸直","x":299,"height":169,"y":172,"width":168},{"name":"猫01/身体","x":340,"height":180,"y":343,"width":122},{"name":"猫01/领带","x":1,"height":156,"y":411,"width":120},{"name":"猫01/右耳","x":155,"height":76,"y":602,"width":90},{"name":"猫01/左耳","x":67,"height":85,"y":602,"width":86},{"name":"猫01/组_1","x":1,"height":185,"y":1,"width":296},{"name":"猫01/右眼","x":1,"height":60,"y":686,"width":59},{"name":"猫01/右眉毛","x":67,"height":5,"y":595,"width":33},{"name":"猫01/左眼","x":247,"height":60,"y":666,"width":59},{"name":"猫01/左眉毛","x":247,"height":12,"y":602,"width":31},{"name":"猫01/眼镜","x":301,"height":63,"y":525,"width":170},{"name":"猫01/胡子","x":123,"height":85,"y":515,"width":176},{"name":"猫01/鼻子","x":67,"height":24,"y":569,"width":28},{"name":"猫01/嘴","x":1,"height":30,"y":299,"width":65},{"name":"猫01/帽子","x":123,"height":102,"y":411,"width":158}],"height":1024,"width":512}
\ No newline at end of file
{
"ver": "1.0.1",
"uuid": "7c83def9-961d-4141-97aa-4b109dddeb0f",
"subMetas": {}
}
\ No newline at end of file
{
"ver": "2.3.5",
"uuid": "406732a3-eaf9-4833-8a01-542ad1189a3e",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 512,
"height": 1024,
"platformSettings": {},
"subMetas": {
"mao_tex": {
"ver": "1.0.4",
"uuid": "d2fab846-619a-43af-98c8-e5d62448ef97",
"rawTextureUuid": "406732a3-eaf9-4833-8a01-542ad1189a3e",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": -7.5,
"offsetY": 138.5,
"trimX": 1,
"trimY": 1,
"width": 495,
"height": 745,
"rawWidth": 512,
"rawHeight": 1024,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}
\ No newline at end of file
{
"ver": "1.1.0",
"uuid": "c551970e-b095-45f3-9f1d-25cde8b8deb1",
"uuid": "b7cb916a-ffb9-41d4-a434-670da0dbd4b0",
"subMetas": {}
}
\ No newline at end of file
This diff is collapsed.
{
"ver": "1.2.9",
"uuid": "0737ce42-24f0-45c6-8e1a-8bdab4f74ba3",
"uuid": "58972144-7d7f-441a-a339-205e9057ca62",
"asyncLoadAssets": false,
"autoReleaseAssets": true,
"subMetas": {}
......
This diff is collapsed.
{
"ver": "1.0.8",
"uuid": "f8b451ff-857c-4ca8-9870-866bc5154a29",
"uuid": "5fb8daa2-5355-44e8-b3ac-754d52205c77",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
......
{
"ver": "1.1.2",
"uuid": "41970e8e-5322-4f22-9782-9531f4e45289",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import Manager from "./Manager/Manager"
import SoundMgr from "./Manager/SoundMgr"
import AssetMgr from "./Manager/AssetMgr"
import ViewMgr from "./Manager/ViewMgr"
import LayerMgr from "./Manager/LayerMgr"
import ModuleMgr from "./Manager/ModuleMgr"
import LoopMgr from "./Manager/LoopMgr"
import { EventConst } from "./ConstDefine/EventConst"
import GameUpdateMgr from "./Manager/GameUpdateMgr"
let Managers=[
LoopMgr,
AssetMgr,
LayerMgr,
SoundMgr,
ViewMgr,
ModuleMgr,
GameUpdateMgr
]
export default class AppFacade{
private static mgrDic:Map<string,Manager>=new Map()
private static mgrProgress:number=null //模块进度
private static progress:number=null //总进度
public static get Progress(){return this.progress}
private static isInitFinish:boolean=null
private static isDestroy:boolean=false
private constructor(){}
private static hideFun:any
private static showFun:any
public static onLoad(){
console.log("onLoad")
this.mgrProgress=0
this.progress=0
this.isInitFinish=false
this.isDestroy=false
this.hideFun=this.onHideGame.bind(this)
this.showFun=this.onShow.bind(this)
cc.game.on(cc.game.EVENT_SHOW, this.onShow, this)
cc.game.on(cc.game.EVENT_HIDE, this.onHideGame, this)
}
public static async onStart(){
console.log("onStart")
let counter=0
for(let mgr of Managers){
await this.addMgr(mgr as any)
this.mgrProgress=(++counter/Managers.length)
}
this.getMgr(AssetMgr).startPreLoad()
this.mgrProgress=1
}
public static onUpdate(){
if(this.isInitFinish==false){
let assetMgr=this.getMgr(AssetMgr)
let updateMgr=this.getMgr(GameUpdateMgr)
if(assetMgr){
//总进度=更新进度+模块加载进度+资源预加载进度
this.progress=(updateMgr&&updateMgr.Progress||0)*0.5+(this.mgrProgress*0.2)+(assetMgr&&assetMgr.PreProgress*0.3||0)
this.progress>=1&&(this.isInitFinish=true)
}
}else{
for(let v of this.mgrDic.values()){
v.update()
}
}
}
public static onLateUpdate(){
if(this.isDestroy) return
for(let v of this.mgrDic.values()){
v.lateUpdate()
}
}
/**
* bug:loopMgr清理了事件,最好先释放
*/
public static async onDestroy(){
cc.game.off(cc.game.EVENT_SHOW, this.onShow, this)
cc.game.off(cc.game.EVENT_HIDE, this.onHideGame, this)
this.onHideGame()
this.isDestroy=true
for(let i=0;i<this.mgrDic.size;++i){
console.log(Managers[i].TypeName)
this.mgrDic.get(Managers[i].TypeName).release()
}
this.mgrDic.clear()
}
public static getMgr<T extends Manager>(type:{new():T;TypeName:string}):T{
let res:T=<T>this.mgrDic.get(type.TypeName)
return res
}
//IManager 要求对象继承于IManager ,用Manager要求对象有一堆属性实现
//T 是最终存入的对象
private static async addMgr<T extends Manager>(type:{new():T;TypeName:string}){
let res:T=<T>this.mgrDic.get(type.TypeName)
if(!res){
res=new type()
await res.start()
this.mgrDic.set(type.TypeName,res)
}
return res
}
private static onHideGame(){
console.log("隐藏到后退或者退出")
cc.systemEvent.emit(EventConst.HideGame)
}
private static onShow(res){
cc.systemEvent.emit(EventConst.ShowGame,res)
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "408a67f8-65fa-4cf1-8cf2-83e20e1a0fd5",
"uuid": "635c923c-a3a5-4520-8111-9a88754b8a87",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
......
{
"ver": "1.1.2",
"uuid": "01a9d787-2186-4fe7-b00b-8ac6f65d5e02",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import AppFacade from "../AppFacade";
import LayerMgr from "../Manager/LayerMgr";
import UIUtil from "../Util/UIUtil";
import View from "./View";
/**
* @param 全屏界面
* 1.需要有Bottom Top Left Right 四个二级节点对齐
* 2.最高级父节点Size=0,0
* 3.【应该只有一级界面是Fullview,内曾是Fullview没意义,middle等节点并不会展开】
*/
export default abstract class FullView extends View{
public widget:cc.Widget=null
public top:cc.Node=null
public bottom:cc.Node=null
public left:cc.Node
public leftTop:cc.Node
public leftBottom:cc.Node
public right:cc.Node
public rightBottom:cc.Node
public rightTop:cc.Node
public middle:cc.Node
public topWidget:cc.Widget=null
public bottomWidget:cc.Widget=null
public leftWidget:cc.Widget=null
public leftTopWidget:cc.Widget
public leftBottomWidget:cc.Widget
public rightWidget:cc.Widget=null
public rightTopWidget:cc.Widget
public rightBottomWidget:cc.Widget
public middleWidth:cc.Widget=null
public abstract getTypeName():string
protected setLayer(){
let layer=AppFacade.getMgr(LayerMgr)
// widget 安装上后,left的值等没有根据父亲更新
this.widget=UIUtil.autoFitCanvas(this.node,layer.bangScreenTopOffset())
this.top=this.getChildNode("Top")
if(this.top){
this.top.setContentSize(cc.view.getDesignResolutionSize())
this.topWidget=this.addCCComp<cc.Widget>(this.top,cc.Widget)
this.topWidget.isAlignTop=true
}
this.bottom=this.getChildNode("Bottom")
if(this.bottom){
this.bottom.setContentSize(cc.view.getDesignResolutionSize())
this.bottomWidget=this.addCCComp<cc.Widget>(this.bottom,cc.Widget)
this.bottomWidget.isAlignBottom=true
}
this.left=this.getChildNode("Left")
if(this.left){
this.left.setContentSize(cc.view.getDesignResolutionSize())
this.leftWidget=this.addCCComp<cc.Widget>(this.left,cc.Widget)
this.leftWidget.isAlignLeft=true
}
this.leftTop=this.getChildNode("LeftTop")
if(this.leftTop){
this.leftTop.setContentSize(cc.view.getDesignResolutionSize())
this.leftTopWidget=this.addCCComp<cc.Widget>(this.leftTop,cc.Widget)
this.leftTopWidget.isAlignLeft=true
this.leftTopWidget.isAlignTop=true
}
this.leftBottom=this.getChildNode("LeftBottom")
if(this.leftBottom){
this.leftBottom.setContentSize(cc.view.getDesignResolutionSize())
this.leftBottomWidget=this.addCCComp<cc.Widget>(this.leftBottom,cc.Widget)
this.leftBottomWidget.isAlignLeft=true
this.leftBottomWidget.isAlignBottom=true
this.leftBottomWidget.updateAlignment()
}
this.right=this.getChildNode("Right")
if(this.right){
this.right.setContentSize(cc.view.getDesignResolutionSize())
this.rightWidget=this.addCCComp<cc.Widget>(this.right,cc.Widget)
this.rightWidget.isAlignRight=true
}
this.rightTop=this.getChildNode("RightTop")
if(this.rightTop){
this.rightTop.setContentSize(cc.view.getDesignResolutionSize())
this.rightTopWidget=this.addCCComp<cc.Widget>(this.rightTop,cc.Widget)
this.rightTopWidget.isAlignRight=true
this.rightTopWidget.isAlignTop=true
}
this.rightBottom=this.getChildNode("RightBottom")
if(this.rightBottom){
this.rightBottom.setContentSize(cc.view.getDesignResolutionSize())
this.rightBottomWidget=this.addCCComp<cc.Widget>(this.rightBottom,cc.Widget)
this.rightBottomWidget.isAlignRight=true
this.rightBottomWidget.isAlignBottom=true
}
this.middle=this.getChildNode("Middle")
if(this.middle){
this.middleWidth=UIUtil.autoFitCanvas(this.middle)
}
}
protected updateAligment(){
this.topWidget&&this.topWidget.updateAlignment()
this.bottomWidget&&this.bottomWidget.updateAlignment()
this.leftWidget&&this.leftWidget.updateAlignment()
this.leftTopWidget&&this.leftTopWidget.updateAlignment()
this.leftBottomWidget&&this.leftBottomWidget.updateAlignment()
this.rightTopWidget&&this.rightTopWidget.updateAlignment()
this.rightBottomWidget&&this.rightBottomWidget.updateAlignment()
this.rightWidget&&this.rightWidget.updateAlignment()
this.middleWidth&&this.middleWidth.updateAlignment()
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "8b8f4199-a46f-42d9-807a-87bf0d003d43",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import { ViewConst } from "../ConstDefine/ViewConst";
import AppFacade from "../AppFacade";
import LayerMgr from "../Manager/LayerMgr";
import UIWindowView from "./UIWindowView";
import View from "./View";
export default class MaskView extends View{
//栈
private viewStack:Array<UIWindowView>=new Array()
//退出队列
private exitQueue:Array<UIWindowView>=new Array()
private newTarget:cc.Node=null
public getTypeName(): string {
return ViewConst.PauseView
}
protected setLayer(){
this.newTarget&&this.setParentData(this.newTarget)
}
protected async getChilds(){
this.node.on(cc.Node.EventType.TOUCH_END,this.onClickMask,this)
this.node.active=true
this.isOpen=true
}
/**
* @param target
* @returns 是否可以显示出来
*/
public bindTarget(target:UIWindowView){
if(!target) return
let init=this.viewStack.length<=0
this.pushStack(target)
if(init){
this.node&&(this.isOpen=true)
}
}
public unBindTarget(target:UIWindowView){
this.popStack(target)
this.tryResycle()
}
/**
* 返回是否已经存入
* @param target
*/
private pushStack(target:UIWindowView){
let lastView=this.viewStack[this.viewStack.length-1]
if(lastView==target) return
let index=this.viewStack.lastIndexOf(target)
if(index>=0){
this.viewStack.splice(index,1)
}
let preView=this.viewStack[this.viewStack.length-1]
this.viewStack.push(target)
this.setParentData(target?.node)
this.popExitQueue(target)
this.popExitQueue(preView)
if(preView){
this.exitQueue.push(preView)
preView.hide()
}
}
private popStack(target:UIWindowView) {
//只是临时退出
if(this.exitQueue.includes(target)){
return
}
let index=this.viewStack.lastIndexOf(target)
if(index>=0){
this.viewStack.splice(index,1)
}
let preView=this.exitQueue.shift()
if(preView){
preView.open()
this.setParentData(preView.node)
}
}
private popExitQueue(target:UIWindowView){
let index=this.exitQueue.lastIndexOf(target)
if(index>=0){
this.exitQueue.splice(index,1)
}
}
private setParentData(node:cc.Node){
if(!node) return
if(this.node){
this.setParent(node.parent)
this.setPosition(cc.Vec2.ZERO_R)
let sibling=node.parent?.childrenCount??0
this.node.setSiblingIndex(sibling+1)
node.setSiblingIndex(sibling)
}else{
this.newTarget=node
}
}
private onClickMask(){
// if(this.viewStack.length>0){
// let view=this.viewStack[0]
// if(view?.IsCanClickMaskClose){
// view.close()
// }
// }
// this.tryResycle()
}
public closeAll(){
let tmpStack=this.viewStack.splice(0)
this.viewStack.length=0
this.exitQueue.length=0
for(let view of tmpStack){
view?.close()
}
this.tryResycle()
}
public isInStack(view:UIWindowView):boolean{
return this.viewStack.includes(view)
}
private tryResycle(){
if(this.viewStack.length<=0){
this.exitQueue.length=0
AppFacade.getMgr(LayerMgr).pushPool(this.node)
this.isOpen=false
}
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "afa23280-0ecb-4d13-9b0a-cdbf0391714b",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import { ViewConst, ViewType } from "../ConstDefine/ViewConst"
import AppFacade from "../AppFacade"
import LayerMgr from "..//Manager/LayerMgr"
import ViewMgr from "..//Manager/ViewMgr"
import FullView from "./FullView"
/**
* UI全屏界面
*/
export default abstract class UIFullView extends FullView{
public abstract getTypeName():string
public getViewType():ViewType{return ViewType.UIFullView}
protected setLayer(){
super.setLayer()
this.changeLayer()
}
protected changeLayer(){
let layer=AppFacade.getMgr(LayerMgr)
layer.setLayer(this.node,layer.UiLayer)
}
public close(){
super.close()
AppFacade.getMgr(ViewMgr).releaseView(this.getTypeName(),ViewConst.ReleaseTime.UI)
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "0b4c5b38-fdae-4880-ac59-d6c7ea228412",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import View from "./View";
import AppFacade from "../AppFacade";
import LayerMgr from "../Manager/LayerMgr";
import MaskView from "./MaskView";
import LoopMgr from "../Manager/LoopMgr";
import ViewMgr from "../Manager/ViewMgr";
import { ResConst } from "../ConstDefine/ResConst";
import { ViewConst, ViewType } from "../ConstDefine/ViewConst";
/**
@param UI窗体
*/
const TWEEN_TIME=0.3
export default abstract class UIWindowView extends View{
//静态变量只有加载模块的时候调用
public static maskView:MaskView=null
private enterTween:cc.Tween=null
private exitTween:cc.Tween=null
private enterPos:cc.Vec3=cc.Vec3.ZERO
private exitPos:cc.Vec3=cc.v3(0,cc.view.getDesignResolutionSize().height)
protected btnClose:cc.Button=null
//允许点击mask关闭
public get IsCanClickMaskClose():boolean{return this.isCanClickMaskClose}
protected isCanClickMaskClose:boolean=true
private closeTimeoutId:number=-1
public abstract getTypeName():string
public getViewType():ViewType{return ViewType.UIWindow}
protected setLayer():void{
let layer=AppFacade.getMgr(LayerMgr)
layer.setLayer(this.node,layer.WindowLayer)
this.enterTween=cc.tween(this.node).to(0,{position:this.exitPos}).to(TWEEN_TIME,{position:this.enterPos},{easing:cc.easing.circInOut})
this.exitTween=cc.tween(this.node).to(0,{position:this.enterPos}).to(TWEEN_TIME,{position:this.exitPos},{easing:cc.easing.expoIn})
}
protected async getChilds(){
if(!UIWindowView.maskView){
UIWindowView.maskView=new MaskView()
UIWindowView.maskView.loadViewAsync(ResConst.UiABName,"Common/MaskView")
}
this.btnClose=this.getChildComp("BtnClose",cc.Button)
this.btnClose?.node.on("click",this.close,this)
await this.getWindowChilds()
}
/** 子类重写这个方法
* 会忘记调用 await this.getChilds()
*/
protected abstract getWindowChilds()
protected onOpenEnter(){}
/** window不能限制,影响窗口再弹 */
public open(){
super.open()
this.clearCloseTimeout()
UIWindowView.maskView?.bindTarget(this)
this.playAnimal(true)
}
public close():void{
if(this.isOpen==false) return
this.clearCloseTimeout()
UIWindowView.maskView?.unBindTarget(this)
this.playAnimal(false)
AppFacade.getMgr(ViewMgr).releaseView(this.getTypeName(),ViewConst.ReleaseTime.UI)
super.close()
// this.closeTimeoutId=AppFacade.getMgr(LoopMgr).setTimeout(()=>{
// AppFacade.getMgr(ViewMgr).releaseView(this.getTypeName(),ViewConst.ReleaseTime.UI)
// super.close()
// },TWEEN_TIME)
}
public hide(){
this.playAnimal(false)
}
public playAnimal(isEnter:boolean){
if(isEnter){
// this.exitTween?.stop()
// this.enterTween?.start()
// AppFacade.getMgr(LoopMgr).setTimeout(this.onOpenEnter.bind(this),TWEEN_TIME)
this.onOpenEnter()
}else{
// this.enterTween?.stop()
// this.exitTween?.start()
}
// AppFacade.getMgr(SoundMgr).playEffect(SoundConst.Window)
}
private clearCloseTimeout(){
AppFacade.getMgr(LoopMgr).clearTimeout(this.closeTimeoutId)
this.closeTimeoutId=-1
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "cda9cb01-2ec6-44fb-95ec-03acf7ec70bd",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import AppFacade from "../AppFacade";
import { EventConst } from "../ConstDefine/EventConst";
import ViewComp from "../ViewComp/ViewComp";
import { ViewType } from "../ConstDefine/ViewConst";
import IView from "../Interface/IView";
import AssetMgr from "../Manager/AssetMgr";
/**
* @param 所有对象的父类
*/
export default class View implements IView {
//【禁止使用】类名会因为编译修改
private getClsName(): string {
return this.constructor.name
}
private static gIndex=0
private instanceId:number=0
public get InstanceId():number{
if(!this.instanceId){
this.instanceId=++View.gIndex
}
return this.instanceId
}
public getTypeName(): string { return "View" }
public getViewType():ViewType{ return ViewType.None}
public get node(): cc.Node { return this.rootNode }
private rootNode: cc.Node
protected isOpen: boolean
public get IsOpen(): boolean { return this.isOpen }
protected resName: string = ""
public get ResName(): string { return this.resName }
protected abPath: string = ""
protected isStarLoad:boolean=false
public get IsStartLoad():boolean{return this.isStarLoad}
protected isLoadFinish: boolean = false //用来判断是否加载完
public get IsLoadFinish():boolean{return this.isLoadFinish}
private viewComps:Map<typeof ViewComp,ViewComp>
//子类写以下方法
protected setLayer(): void { }
protected async getChilds() { }
protected async onUpdateData(data?: Object) { }
protected onOpen(): void { }
protected onClose(): void { }
/**是否可以设置active */
public isCanActiveClose:boolean=true
public isCanActiveOpen:boolean=true
public async loadViewAsync(abPath: string, resName: string) {
this.isStarLoad=true
return new Promise(async (resolve)=>{
this.resName = resName
this.abPath = abPath
try{
let prefab = await AppFacade.getMgr(AssetMgr).loadAssetAsync<cc.Prefab>(abPath, resName, cc.Prefab)
this.rootNode = cc.instantiate(prefab)
await this.loadViewFinish()
resolve(this)
}catch(err){
console.log(err)
}
})
}
public async loadViewClone(prefab: cc.Node, instantiate: boolean)
public async loadViewClone(prefab: cc.Prefab)
public async loadViewClone(prefab: any, instantiate: boolean = true) {
this.isStarLoad=true
return new Promise(async (resolve)=>{
if (!prefab) {
console.error("loadViewClone prefab is null")
return
}
this.rootNode = instantiate && cc.instantiate(prefab) || prefab
await this.loadViewFinish()
resolve(this)
})
}
protected async loadViewFinish(){
this.setLayer()
await this.getChilds()
this.viewComps?.forEach((comp)=>comp.getChilds())
this.isLoadFinish = true
}
public isRootView(): boolean { return cc.isValid(this.node) }
public isParentView(): boolean { return this.isRootView() && cc.isValid(this.node.parent) }
//防止没加载完成的时候多次调用
public async updateData(data?: Object) {
if (this.isLoadFinish == false)
return
await this.onUpdateData(data)
this.viewComps?.forEach((comp)=>comp.updateData(data))
}
public open(): void {
if (this.isLoadFinish==false||this.isOpen==true) return
this.isOpen = true
this.viewComps?.forEach((comp)=>comp.open())
if(this.isCanActiveOpen&&this.isRootView()){
this.node.active=true
}
this.isParentView() && this.node.setSiblingIndex(this.node.parent.childrenCount)
this.emitEvent(EventConst.OpenView)
this.onOpen()
}
protected emitEvent(event:string){
cc.systemEvent.emit(event,this.getTypeName(),this.getViewType())
}
public close(): void {
if (this.isOpen==false) return
this.isOpen = false
this.viewComps?.forEach((comp)=>comp.close())
if(this.isCanActiveClose&&this.isRootView()){
this.node.active=false
}
this.onClose()
this.emitEvent(EventConst.CloseView)
}
/**
* 事件在loop中释放了
*/
public release(): void {
this.onRelsese()
this.isLoadFinish = false
this.node?.destroy()
this.viewComps?.forEach((comp)=>comp.release())
AppFacade.getMgr(AssetMgr).releaseAsset(this.abPath,this.resName)
}
protected onRelsese(){}
public setActive(active:boolean){
this.isRootView()&&(this.node.active=active)
}
public setParent(parent: cc.Node) {
this.isRootView() && (this.node.parent = parent)
}
public setPosition(newPosOrX: cc.Vec2 | cc.Vec3) {
this.isRootView() && (this.node.setPosition(newPosOrX))
}
public setRotation(rotation: number) {
this.isRootView() && (this.node.angle = -rotation)
}
public getWorldPos(): cc.Vec3 {
let res = cc.Vec3.ZERO
if (this.isParentView()) {
res = this.node.parent.convertToWorldSpaceAR(this.node.position)
}
return res
}
public setWorldPos(worldPos: cc.Vec3) {
if (this.isParentView()) {
this.node.position = this.node.parent.convertToNodeSpaceAR(worldPos)
}
}
protected addViewComp(type:typeof ViewComp):ViewComp{
if(!this.viewComps){
this.viewComps=new Map()
}
let c=this.viewComps.get(type)
if(!c){
c=new type(this)
this.viewComps.set(type,c)
}
return c
}
public getViewComp<T extends ViewComp>(type:typeof ViewComp):T{
if(!this.viewComps) return
let comp=this.viewComps.get(type)
return <T>comp
}
protected getChildNode(url: string): cc.Node {
if (!this.isRootView()) return null
if (url === "") return this.node
return cc.find(url, this.node)
}
protected getChildComp<T extends cc.Component>(url: string, type: { prototype: T }): T {
if (!this.isRootView()) return null
let node = this.getChildNode(url)
!node && (cc.error(this.resName, url, "not exit", "getChildComp"))
return node && node.getComponent(type)
}
protected getChildComps<T extends cc.Component>(url: string, type: { prototype: T }): T[] {
if (!this.isRootView()) return null
let node = this.getChildNode(url)
!node && (cc.error(this.resName, url, "not exit", "getChildComp"))
return node && node.getComponentsInChildren(type)
}
protected addCCComp<T extends cc.Component>(node: cc.Node, type: new () => cc.Component): T {
if (!node) return null
let res = node.getComponent(type)
if (!res) {
res = node.addComponent(type) as T
}
return res
}
protected setName(name: string) {
this.isRootView() && (this.node.name = name)
}
public getPathInLayer():string{
if(!this.isRootView()) return ""
let p=this.node.parent
let res=this.node.name
while(cc.isValid(p)){
res=p.name+"/"+res
p=p.parent
}
return res
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "803110d8-07ce-4d32-b11e-61b7c7efee33",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "db5f0937-64e8-4998-83b6-ddd2e1cd2869",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
export namespace AppConst{
//语言定义 Zn中文 Fan繁体 En英文
export let LangZn="CN"
export let LangFan="TC"
export let LangEn="EN"
export let Lang=LangZn
export let IsDebug=true;//false
export let IsAuto=true;//false
export let GameOptimize=false //启动优化
export let GameFrameRate=60//60帧
export let GameFrameInterval=1/GameFrameRate //减少update调用次数
export let Width=2176
export let Height=1600
export let Ip="127.0.0.1"
export let Port="8081"
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "8b93a4cd-8f62-4a53-b362-a5292ae4bc34",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
/**
* @param 事件
*/
export const EventConst = {
//输入系统
TouchStart: "TouchStart",
TouchStay: "TouchStay",
TouchEnd: "TouchEnd",
TouchCancle: "TouchCancle",
TouchMove: "TouchMove",
ChangeTouchState:"ChangeTouchState",//修改操作状态
//全局
BtnForceClickOpen: "BtnForceClickOpen",//ForceClick脚本附加事件
BtnForceClickClose: "BtnForceClickClose",//ForceClick脚本附加事件
TBCLRState: "TBCLRState",//tbclr方位界面动画状态
OpenView: "OpenView", //打开界面
CloseView: "CloseView", //关闭界面
CloseAllWindow: "CloseAllWindow",//关闭所有窗口界面
SaveDataPre: "SaveDataPre", //存档前
//游戏相关
MainMenu:"MainMenu", //进入主菜单
EnterGame: "EnterGame",//进入游戏
ShowGame:"ShowGame", //展开游戏
HideGame: "HideGame", //退出游戏
LoadingFinish: "LoadingFinish", //更新完成
LoadingShow: "LoadingShow",//进度页面
LoadingHide: "LoadingHide",//隐藏进度页面
RoleMove:"RoleMove",
//广告
TemplateViewAdStatus:"TemplateViewAdStatus0", //模板【界面】广告的状态
JumpToStartView:"JumpToStartView",//跳到开始界面
JumpToGameView:"JumpToGameView",//跳到游戏
JumpToOverView:"JumpToOverView",//跳到结算
JumpToTalentSelectView:"JumpToTalentSelectView",//跳到天赋
JumoToAttrView:"JumoToAttrView",//跳到属性
JumpToStatisticsView:"JumpToStatisticsView",//跳到总结
//debug
StartAuto:"StartAuto", //开始自动跑
SelectTalentDebug:"SelectTalentDebug",//点击天赋十连
SetAttrValueDebug:"SetAttrValueDebug",
PlayGameDebug:"PlayGameDebug",
OverViewDebug:"OverViewDebug",
//属性
AttrUpdate:"UpdateAttr",//更新属性
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "308804b0-7159-435e-91f5-6e7ed528fdd8",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export enum SubContextEvent{
InitData="InitData",
Open="Open",
Close="Close",
SetValue="SetValue",
ReciveInvite="ReciveInvite",
}
export enum ChannelType
{
//小游戏
None,Weixin,ByteDance,Kuaishou,OPPO,VIVO,_4399,
//Android
Android,Android_Ohayoo,_233,Android_MOMOYU,
//IOS
IOS,IOS_Ohayoo,
}
export namespace PlatformConst{
//微信 start
//web可以有多个渠道,没办法区分只能赋给id
// export let Channel=ChannelType.Weixin
// export let Channel=ChannelType.ByteDance
export let Channel=ChannelType.None
//分享query数字
export let ShareQuery={
None:"0",
inviteFriend:"1", //邀请好友 给 shareMessageToFriend 用
inviteNum:"2", //邀请数量
sendDiamond:"3", //送钻石
}
export let InviteFriendDiamond=20 //邀请好友奖励
export let GiveFriendDiamond=5 //赠送好友钻石
export function getWXShareData(openId){
return {
title: '皇帝模拟器',
// imageUrlId:getPlatformShareId(),
// imageUrl: getPlatfomShareImg(),
query: "inviteOpenId=" + openId,
}
}
function getPlatformShareId():string{
if(PlatformConst.Channel==ChannelType.Weixin){
return "gkkrxQYURhaacqjt7nkPdg=="
}
}
function getPlatfomShareImg():string{
if(PlatformConst.Channel==ChannelType.Weixin){
// return "https://mmocgame.qpic.cn/wechatgame/w0jhXlUMxvQnf3I2WMFnzfetNbBgVIRTG5UVrlOFBjKRsqkpZHzCR2dDocU8GLD5/0"
return ""
}
}
/** appId */
export function getAppKey():string{
if(PlatformConst.Channel==ChannelType.OPPO){
return "24em7kOC6t40k4Cs040ScgWWK"
}else if(PlatformConst.Channel==ChannelType.VIVO){
return "61506548aa5cab5f8803ed3f8d422a9a"
}
}
export function getAppSecrete():string{
if(PlatformConst.Channel==ChannelType.OPPO){
return "E2cdf7a3773b646EbcD77Bd6eec2A947"
}else if(PlatformConst.Channel==ChannelType.VIVO){
return "d1f2afc75fc0b36ff22af3159744edf6"
}
}
export function getPkgName():string{
if(PlatformConst.Channel==ChannelType.OPPO){
return "gzyy.msyx.nearme.gamecenter"
}else if(PlatformConst.Channel==ChannelType.VIVO){
return "com.gzyy.msyx.vivominigame"
}
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "bd4cfa23-db06-4478-bb95-f34967f16c0d",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
//资源相关常量
export namespace ResConst{
export let emptyABName="";
export let AudioABName="res/audio"
export let PrefabsABName="prefabs"
export let JsonABName="json"
export let Role1ABName="role1"
export let UiABName="UI"
export let AiABName="Ai"
export let ConfigABName="config"
export let ResourcesABName="resources"
export let ParticleABName="Particle"
export let SpineABName="Spine"
export let SkillSVGName="skill"
export let snd={
button:"button",
click:"click",
right:"correct",
wrong:"incorrect",
lack:"lack",
finish:"finish",
painted:"painted"
}
//必须加载完
export const AwaitLoadAssets=[
]
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "a523a2f0-b168-4822-a6b9-69a4c7fea0c3",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export enum ViewType{
None=0,
UI=1<<0,
UIWindow=(1<<1)|UI,
UIFullView=(1<<2)|UI,
UITabView=(1<<3)|UIWindow,
SceneView=(1<<4),
}
export namespace ViewType{
export function isUI(viewType:ViewType){
let res=viewType&ViewType.UI
return res==ViewType.UI
}
export function isUIWindow(viewType:ViewType){
let res=viewType&ViewType.UIWindow
return res==ViewType.UIWindow
}
export function isScene(viewType:ViewType){
let res=viewType&ViewType.SceneView
return res==ViewType.SceneView
}
}
export namespace ViewConst{
//释放时间
export const ReleaseTime={
UI:5,
Particle:8,
SceneObj:10,
}
//View
export const TipsView="TipsView"
//SceneView
export const MenuView="bg"
//UIWindow
export const CardView="CardView"
export const PauseView="PauseView"
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "37363f43-0b03-46fb-9a8c-bb40d7df82c6",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import AppFacade from "./AppFacade";
import ViewMgr from "./Manager/ViewMgr";
import View from "./BaseView/View";
import IController from "./Interface/IController";
//controller操作数据model和view
export default class Controller implements IController{
protected constructor(){}
protected static _inst=null
public static get Inst():Controller{
if(this._inst==null){
this._inst=new Controller()
}
return this._inst
}
public async init() {}
public release() {}
// public async getView(viewName:string,type:typeof View){
// let view=AppFacade.getMgr(ViewMgr).openView(viewName,type)
// if(!view.IsStartLoad){
// await view.loadViewClone(cc.find("Canvas/"+viewName),false);
// }
// }
public async getView(viewName:string,type:typeof View){
let view=AppFacade.getMgr(ViewMgr).openView(viewName,type)
if(!view.IsStartLoad){
await view.loadViewClone(cc.find("Canvas/"+viewName),false);
}
// await view.updateData()
// view.open()
return view;
}
// public async getView(viewName:string,type:typeof View,resName:string){
// let view=AppFacade.getMgr(ViewMgr).openView(viewName,type)
// if(!view.IsStartLoad){
// await view.loadViewAsync(ResConst.PrefabsABName,resName)
// }
// // await view.updateData()
// // view.open()
// return view;
// }
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "4fa632b5-6def-4037-836c-32d36b5e46d0",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "9846b613-68a1-44c2-b47a-bb94057036f7",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
/**
* @param 函数接口
*/
export interface ICreateFunc<T>{
():T
}
export interface IPredicate<T>{
(t:T):boolean
}
export interface IParamter<T>{
(t:T,i?:number):void
}
export interface ILimitFunc{
(arr:any,i:number):void
}
{
"ver": "1.0.8",
"uuid": "f5debb73-a049-43ff-bd2f-32bb61c2c649",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export default interface IController{
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "28e09d98-3a46-47f8-a4d3-946ed3c4f5f2",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export default interface IManager{}
{
"ver": "1.0.8",
"uuid": "a9a8a69e-85a0-44f6-a377-b46717032148",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export default interface IModel{
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "4e08a9fd-23e6-4de8-966e-14be66928679",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
export default interface IView{
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "53428666-7299-4b1a-94c2-a1b5ebf9481a",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import AppFacade from "./AppFacade";
const {ccclass, property} = cc._decorator;
//启动动态图集 必须放这里
cc.macro.CLEANUP_IMAGE_CACHE = false
cc.dynamicAtlasManager.enabled = true
@ccclass
export default class Main extends cc.Component {
onLoad(){
AppFacade.onLoad()
}
start () {
try{
AppFacade.onStart()
}catch(err){
cc.error("运行出错",err)
}
}
update(){
try{
AppFacade.onUpdate()
}catch(err){
cc.error("运行错误",err)
}
}
lateUpdate(){
AppFacade.onLateUpdate()
}
onDestroy(){
AppFacade.onDestroy()
}
}
{
"ver": "1.0.8",
"uuid": "bf6d8a0d-d989-49fe-a23d-19ec171e58fe",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "b06e0643-fca0-4540-ad36-176d2cee4e94",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import { ResConst } from "../ConstDefine/ResConst"
import Manager from "./Manager"
export default class AssetMgr extends Manager {
static get TypeName(): string { return "AssetMgr" }
private preProgress: number = 0
public get PreProgress(): number { return this.preProgress }
public async start() {
console.log("AssetMgr onStart")
}
public release() {
console.log("AssetMgr onRelease")
}
public async startPreLoad() {
let promises = []
for (let v of ResConst.AwaitLoadAssets) {
promises.push(this.preLoadAsset(v[0], v[1]))
}
await Promise.all(promises)
this.preProgress = 1
// this.startNoAwaitLoad()
}
// private startNoAwaitLoad() {
// this.preLoadAsset(ResConst.UiABName, "Scene/SceneObj/Player", cc.Prefab)
// this.preLoadAsset(ResConst.UiABName, "Menu/MenuView", cc.Prefab)
// this.preLoadAsset(ResConst.UiABName, "Bg/BgView", cc.Prefab)
// }
// private allProgress() {
// return ResConst.AwaitLoadAssets.length
// }
/**
* 预加载不需要等待
*/
public async preLoadAsset(abName: string, resName: string, type?: typeof cc.Asset) {
return new Promise<void>((resolve, reject) => {
cc.assetManager.loadBundle(abName, (err, bundle: cc.AssetManager.Bundle) => {
if (!err) {
bundle.preload(resName, type, (err, items) => {
resolve()
})
} else {
reject()
}
})
})
}
/**
* 预加载不需要等待
* ""表示整个目录
*/
public preLoadAssetDir(abName: string, dir: string = "", type: typeof cc.Asset) {
cc.assetManager.loadBundle(abName, (err, bundle: cc.AssetManager.Bundle) => {
if (!err) {
bundle.preloadDir(dir, type, (err, items) => { })
}
})
}
//读取目录下所有类型文件
public loadAssetDirAsync<T extends cc.Asset>(abName: string, type: typeof cc.Asset = cc.Asset): Promise<T[]> {
return new Promise((resolve, reject) => {
cc.assetManager.loadBundle(abName, (err, bundle) => {
if (err) {
cc.error("loadBundleAsync error", abName, err)
reject(err)
} else {
bundle.loadDir("./",type,(err,assets)=>{
if (err) {
cc.error("loadAssetAsync error")
reject(err)
}
else {
// assets?.addRef()
resolve(<T[]>assets)
}
})
}
})
})
}
public loadAssetAsync<T extends cc.Asset>(abName: string, resName: string, type: typeof cc.Asset = cc.Asset): Promise<T> {
return new Promise((resolve, reject) => {
cc.assetManager.loadBundle(abName, (err, bundle) => {
if (err) {
cc.error("loadBundleAsync error", abName, resName, err)
reject(err)
} else {
bundle.load(resName, type,
//complete
(err, assets) => {
if (err) {
cc.error("loadAssetAsync error", resName)
reject(err)
}
else {
// assets?.addRef()
resolve(<T>assets)
}
})
}
})
})
}
public releaseAsset(asset: cc.Asset, _?)
public releaseAsset(abName: string, resName: string)
public releaseAsset(a1: any, a2: any) {
if (a1 instanceof cc.Asset) {
if (cc.isValid(a1)) {
a1?.decRef()
}
} else {
if (!a1 || !a2) return
let ab = cc.assetManager.getBundle(a1)
let info: Record<string, any> = ab.getInfoWithPath(a2)
let uuid = info?.uuid
let asset = cc.assetManager.assets?.get(uuid)
asset?.decRef()
if (asset?.refCount <= 0) {
// console.log("释放",asset?.name,cc.assetManager.assets?.count)
}
}
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "6c69587a-b010-4680-921e-1822c7b70123",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
class EventInfo{
public constructor(public callback:Function,public target?:any){}
}
export default class EventMgr{
private static _infoMap:Map<string,Array<EventInfo>>=new Map()
public static on(key:string,cb:Function,target?:any){
let arr=this._infoMap.get(key)
if(!arr){
arr=new Array()
this._infoMap.set(key,arr)
}
arr.push(new EventInfo(cb,target))
}
public static off(key:string,cb:Function,target?:any){
let arr=this._infoMap.get(key)
if(!arr) return
for(let i=arr.length-1;i>=0;i--){
let info=arr[i]
if(target){
if(info.callback==cb&&info.target==target){
arr.splice(i)
}
}else{
if(info.callback==cb){
arr.splice(i)
}
}
}
}
public static emit(key:string,arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any){
let arr=this._infoMap.get(key)
if(!arr||arr.length<=0) return
for(let info of arr){
info?.callback?.call(info?.target,arg1,arg2,arg3,arg4,arg5)
}
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "bf77ba53-2ee7-4988-8735-7267f3435cd0",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import Manager from "./Manager";
import { EventConst } from "../ConstDefine/EventConst";
import { ChannelType, PlatformConst } from "../ConstDefine/PlatformConst"
//负责游戏更新
export default class GameUpdateMgr extends Manager {
static get TypeName(): string { return "GameUpdateMgr" }
private progress: number = null
public get Progress(): number { return this.progress }
public async start() {
console.log("开始更新...")
this.progress = 0
this.startUpdate()
this.onUpdateFinish()
console.log("更新完成...")
}
public release() {
}
//检测资源
private async startUpdate() {
return new Promise<void>((resovle)=>{
if (PlatformConst.Channel==ChannelType.Weixin||PlatformConst.Channel==ChannelType.ByteDance) {
const mgr = wx.getUpdateManager()
console.log("onCheckForUpdate",mgr)
if (mgr) {
mgr.onCheckForUpdate((res) => {
// 请求完新版本信息的回调
if (res.hasUpdate) {
//如果内存卡有存储游戏相关的离线文件,在更新版本的时候需要清除,避免废文件越来越多
wx.showToast({ icon: "none", title: "有新版本了,正在下载中..", duration: 600000 });//10分钟
}else{
resovle()
}
})
mgr.onUpdateFailed(function () {
wx.hideToast()
wx.showModal({
content: '新版本下载失败了,点击确定重启游戏',
title: '更新提示',
showCancel: false,
success: function (res) {
wx.exitMiniProgram()
resovle()
}
})
console.log("onUpdateFailed")
})
mgr.onUpdateReady(function () {
wx.hideToast();
wx.showModal({
content: '新版本已经准备好了,点击确定重启应用',
title: '更新提示',
showCancel: false,
success: function (res) {
// if (res.confirm) {
// // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
// mgr.applyUpdate()
// }else{
// }
mgr.applyUpdate()
resovle()
}
})
console.log("onUpdateReady")
})
}else{
resovle()
}
}
else{
resovle()
}
})
}
private onUpdateFinish(): void {
this.progress = 1
cc.systemEvent.emit(EventConst.LoadingFinish)
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "30c38aed-87fd-4038-acae-d198e771fbcf",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import { AppConst } from "../ConstDefine/AppConst"
import UIUtil from "../Util/UIUtil"
import Manager from "./Manager"
/**
* @params 管理分辨率 层级
*/
const PoolLayer = "PoolLayer"
const WindowLayer="WindowLayer"
const BangScreenOffSet = 70
const FAR_POS = cc.v3(-10000, -10000)
export default class LayerMgr extends Manager {
static get TypeName(): string { return "LayerMgr" }
private uiRoot: cc.Node = null
public get UIRoot(): cc.Node { return this.uiRoot }
private root: cc.Node
public get Root(): cc.Node { return this.root }
//对象池池层级
private poolLayer: cc.Node = null
public get PoolLayer() { return this.poolLayer }
//场景层start
//背景图
private sceneBackLayer: cc.Node = null
public get SceneBackLayer() { return this.sceneBackLayer }
//场景层
private sceneLayer: cc.Node = null
public get SceneLayer() { return this.sceneLayer }
//场景底层
private sceneTopLayer: cc.Node
public get SceneTopLayer() { return this.sceneTopLayer }
//场景层end
//ui层start
//飘血
private flybllodLayer: cc.Node = null
public get FlybllodLayer() { return this.flybllodLayer }
private uiLayer: cc.Node = null
//ui图标层
public get UiLayer() { return this.uiLayer }
//窗口
private windowLayer: cc.Node = null
public get WindowLayer() { return this.windowLayer }
private windowTopLayer: cc.Node = null
public get WindowTopLayer() { return this.windowTopLayer }
//广播
private broadcastLayer: cc.Node = null
public get BroadcastLayer() { return this.broadcastLayer }
//弹窗
private tipViewLayer: cc.Node = null
public get TipViewLayer() { return this.tipViewLayer }
//引导
private guideLayer: cc.Node = null
public get GuideLayer() { return this.guideLayer }
//顶层
private topLayer: cc.Node = null
public get TopLayer() { return this.topLayer }
//ui层end
private layers: cc.Node[] = null
private index: number = 1
private uiViews: Array<cc.Node> = null
public async start() {
// cc.view.enableAutoFullScreen(false)
this.uiRoot = cc.find("Canvas")
cc.game.addPersistRootNode(this.uiRoot)
this.root = cc.find("Root")
if(this.root){
cc.game.addPersistRootNode(this.root)
}
else
{
this.root=this.uiRoot;
}
// 小程序设置无效
// let screen=cc.view.getFrameSize()
// cc.view.setFrameSize(screen.width*0.5,screen.height*0.5)
//手机设备和pc返回的不一样【神经病,pc返回width/height,应该是height/widg】
//let cRatio=cc.view.getDevicePixelRatio()
let policy = this.isFitWidth() && cc.ResolutionPolicy.FIXED_WIDTH || cc.ResolutionPolicy.FIXED_HEIGHT
// cc.view.setDesignResolutionSize(720, 1280, policy)
cc.view.setDesignResolutionSize(AppConst.Width, AppConst.Height, policy)
this.layers = new Array()
this.createLayers()
this.uiViews = [this.flybllodLayer, this.uiLayer, this.windowLayer, this.windowTopLayer, this.tipViewLayer, this.guideLayer, this.topLayer]
console.log("LayerMgr onStart")
}
public release() {
console.log("LayerMgr onRelease")
this.uiViews.length = 0
if (cc.isValid(this.uiRoot)) {
this.uiRoot.destroyAllChildren()
}
this.uiRoot = null
this.layers.length = 0
this.index = 1
}
private createLayers(): void {
this.poolLayer = this.createLayer(PoolLayer, cc.v2(-100000, -100000))
//场景层
this.sceneBackLayer = this.createLayer("SceneBackLayer")
this.sceneLayer = this.createLayer("SceneLayer")
this.sceneTopLayer = this.createLayer("SceneTopLayer")
//ui层
this.flybllodLayer = this.createLayer("FlybllodLayer")
this.uiLayer = this.createLayer("UiLayer")
this.windowLayer = this.createLayer(WindowLayer)
this.windowTopLayer = this.createLayer("WindowTopLayer")
this.broadcastLayer = this.createLayer("BroadcastLayer")
this.tipViewLayer = this.createLayer("TipViewLayer")
this.guideLayer = this.createLayer("GuideLayer")
this.topLayer = this.createLayer("TopLayer")
}
private createLayer(layerName: string, pos: cc.Vec2 = cc.Vec2.ZERO): cc.Node {
let node = new cc.Node(layerName)
this.layers.push(node)
node.setParent(this.uiRoot)
if (layerName != PoolLayer) {
UIUtil.autoFitCanvas(node)
}
node.setSiblingIndex(this.index++)
node.setPosition(pos)
return node
}
/**
* setSiblingIndex 设置同节点层级排序
* zIndex和zOrder是同一个东西。设置渲染顺序,只能影响同一级节点
* 节点渲染都是先渲染自己再渲染子节点
*/
public setLayer(node: cc.Node, layer: cc.Node, offset: number = -1) {
if (!cc.isValid(node)) return
node.parent = layer
node.setSiblingIndex(layer.childrenCount + offset)
}
public pushPool(node: cc.Node) {
if (!cc.isValid(node)) return
node.setParent(this.poolLayer)
node.setPosition(FAR_POS)
}
/**
* @param 是否是刘海屏幕
*/
public isHasBangScreen() {
return this.getDeviceRatio() >= 2
}
/**
* @param 刘海屏偏移
*/
public bangScreenTopOffset(): number {
if (this.isHasBangScreen()) {
return BangScreenOffSet
}
return 0
}
/**
* //手机设备和pc返回的不一样【神经病,pc返回width/height,应该是height/widg】
//let cRatio=cc.view.getDevicePixelRatio()
*/
public getDeviceRatio(): number {
let size = cc.view.getFrameSize()
let ratio = Math.max(size.height, size.width) / Math.min(size.height, size.width)
return ratio
}
public findNode(path: string): cc.Node {
return cc.find(path, this.uiRoot)
}
/**
* uiViews 中的是ui界面,永远显示在屏幕上
*/
public foreverShowUiView(cameraLocPos: cc.Vec3) {
for (let view of this.uiViews) {
view.position = cameraLocPos
}
}
//适配后的分辨率 用cc.winSize就可以了
public getFitedSceneResolution(): cc.Size {
return this.sceneLayer.getContentSize()
}
/** 是否是宽度适配 */
public isFitWidth(): boolean {
let cRatio = this.getDeviceRatio()
let dsize = cc.view.getDesignResolutionSize()
let dRatio = dsize.height / dsize.width
let isFitWidth = cRatio > dRatio
return isFitWidth
}
//全屏特效需要适配屏幕
public fitScreen(node: cc.Node) {
if (!node?.isValid) return
let cRatio = this.getDeviceRatio()
let dsize = cc.view.getDesignResolutionSize()
let dRatio = dsize.height / dsize.width
let paramScale = node.scale || 1
if (this.isFitWidth()) {
node.scale = paramScale * (cRatio / dRatio)
} else {
node.scale = paramScale * (dRatio / cRatio)
}
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "04d4d6d3-121e-4d8b-8a7a-f0f720fc5958",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import { AppConst } from "../ConstDefine/AppConst";
import { EventConst } from "../ConstDefine/EventConst";
import { ILimitFunc } from "../Interface/FuncInterface";
import Manager from "./Manager";
/**
* @param js自带的interval和timeout不好管理容易造成内存泄露尽量不要使用
*/
class TimeoutInfo {
constructor(public func: Function, public timer: number, public id: number = -1) { }
}
class InterInfo {
constructor(public func: Function, public interval: number, public id: number = -1, public timer = 0) { }
}
class DelayInfo {
constructor(public func: Function, public couter: number = 0) { }
}
class LimitInfo {
constructor(public iterator: ILimitFunc, public arr: Array<any>, public limit: number, public resolve: any, public reject: any, public running: number = 0) { }
}
export default class LoopMgr extends Manager {
static get TypeName(): string { return "LoopMgr" }
private updateDic: Map<number, Function> = new Map()
private fixedDic: Map<number, Function> = new Map()
private lateUpdateDic: Map<number, Function> = new Map()
private timeoutDic: Map<number, TimeoutInfo> = new Map()
private intervalDic: Map<number, InterInfo> = new Map()
private delayOneFrames: Array<DelayInfo> = new Array()
private updateFramer: number = 0
private fixedNowTime: number = 0
private limitDic: Map<number, LimitInfo> = new Map()
private deleteLimits: Array<number> = new Array()
private framer: number = 0
public get Frame(): number { return this.framer }
private static LoopIndex: number = 0
async start() {
console.log("LoopMgr onStart")
}
public release() {
console.log("LoopMgr onRelease")
this.updateDic.clear()
this.lateUpdateDic.clear()
this.fixedDic.clear()
this.limitDic.clear()
for (let v of this.intervalDic) {
if (v[1].id != -1) {
clearInterval(v[1].id)
}
}
for (let v of this.timeoutDic) {
if (v[1].id != -1) {
clearTimeout(v[1].id)
}
}
this.intervalDic.clear()
this.timeoutDic.clear()
LoopMgr.LoopIndex = 0
this.clearEvents()
cc.Tween.stopAll()
this.updateFramer = 0
this.fixedNowTime = 0
}
public update(): void {
this.framer = (++this.framer) % Number.MIN_SAFE_INTEGER
//fixedupdate
this.fixedNowTime += cc.director.getDeltaTime()
let delta = AppConst.GameFrameRate
while (this.fixedNowTime > delta) {
this.fixedDic.forEach((v) => { v && v() })
this.fixedNowTime -= delta
}
//update
if (this.isCanUpdate()) {
this.updateDic.forEach((v, key) => { v && v() })
this.runLimit()
}
}
public lateUpdate(): void {
//lateupdate不优化,一定每帧执行的才放这里
this.lateUpdateDic.forEach((v) => { v() })
let v: DelayInfo = null
for (let i = this.delayOneFrames.length - 1; i >= 0; --i) {
v = this.delayOneFrames[i]
if (v.couter >= 1) {
v.func && v.func()
this.delayOneFrames.splice(i, 1)
}
}
this.delayOneFrames.forEach((v) => { v.couter++ })
}
//-----------------------------公开外部方法start--------------------------------
/**
* 分帧执行await async第一次会等待回调返回,之后就直接执行
* @param arr
* @param iterator 每帧如何迭代arr
* @param limit 每帧最多执行多少次
*/
public async eachLimit(arr: Array<any>, iterator: ILimitFunc, limit: number) {
return new Promise((resolve, reject) => {
let info = new LimitInfo(iterator, arr, limit, resolve, reject)
this.limitDic.set(LoopMgr.LoopIndex++, info)
})
}
public addUpdate(func: Function): number {
let id = LoopMgr.LoopIndex++
this.add(id, func, this.updateDic)
return id
}
public remvoeUpdate(id: number) {
this.remove(id, this.updateDic)
}
public addFixedUpdate(func: Function): number {
let id = LoopMgr.LoopIndex++
this.add(id, func, this.fixedDic)
return id
}
public removeFixed(id: number) {
this.remove(id, this.fixedDic)
}
public addLateUpdate(func: Function): number {
let id = LoopMgr.LoopIndex++
this.add(id, func, this.lateUpdateDic)
return id
}
public removeLateUpdate(id: number) {
this.remove(id, this.lateUpdateDic)
}
public setTimeout(func: Function, second: number): number {
let tinfo = new TimeoutInfo(func, second)
tinfo.id = setTimeout(func, second * 1000)
this.timeoutDic.set(tinfo.id, tinfo)
return tinfo.id
}
/**
* 等待多少秒,0会间隔一帧
* 用于协程
*/
public async waitForTime(second: number) {
return new Promise<number>((resolve) => {
let id=this.setTimeout(() => {
resolve(id)
}, second)
})
}
public clearTimeout(id: number) {
if (id < 0) return
clearTimeout(id)
if(this.timeoutDic.has(id)){
this.timeoutDic.delete(id)
}
}
public clearInterval(id: number) {
if (id <0) return
if(this.intervalDic.has(id)){
this.intervalDic.delete(id)
}else{
console.error("clearInterval 不存在的id")
}
clearInterval(id)
}
public setInterval(func: Function, second: number) {
let tinfo = new InterInfo(func, second)
tinfo.id = setInterval(func, second * 1000)
this.intervalDic.set(tinfo.id, tinfo)
return tinfo.id
}
public delayOneFrame(func: Function) {
this.delayOneFrames.push(new DelayInfo(func))
}
//-----------------------------公开外部方法start--------------------------------
private add(id: number, func: Function, map: Map<number, Function>) {
if (map.has(id)) return
map.set(id, func)
}
private remove(id: number, map: Map<number, Function>) {
map.delete(id)
}
private clearEvents() {
for (let v in EventConst) {
cc.systemEvent.removeAll(v)
}
}
/**
* 隔帧执行
*/
private isCanUpdate(): boolean {
if (AppConst.GameFrameInterval <= 0) return true
this.updateFramer--
if (this.updateFramer <= 0) {
this.updateFramer = AppConst.GameFrameInterval
return true
}
return false
}
/**
* await async在分帧没意义,await卡几十帧,之后一帧就被执行完了
*/
private runLimit() {
this.deleteLimits.length = 0
for (const [key, info] of this.limitDic.entries()) {
let i = 0
while (info.running < info.arr.length && i < info.limit) {
info.iterator(info.arr[info.running], info.running)
info.running++
i++
}
if (info.running >= info.arr.length) {
this.deleteLimits.push(key)
info.resolve()
}
}
this.deleteLimits.forEach((key) => {
this.limitDic.delete(key)
})
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "6f857b7e-6dec-4234-aba5-6bac9c9184fc",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import IManager from "../Interface/IManager";
export default abstract class Manager implements IManager{
//注释父类的的TypeName让编译器自动检查子类提示
//static get TypeName(): string{return "Manager"}
async start(){}
update():void{}
lateUpdate():void{}
release(){}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "d98090ce-fe3a-4842-9124-fc68f61dfdbe",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import MenuController from "../../Game/MenuController";
import Controller from "../Controller";
import Manager from "./Manager";
export let InitModules=[
MenuController
]
export default class ModuleMgr extends Manager{
static get TypeName():string{return "ModuleMgr"}
private modules:Array<Controller>=null
public async start(){
console.log("开始初始化模块")
this.modules=new Array()
let modules=InitModules
let promises=[]
for(let mod of modules){
this.modules.push(mod.Inst)
promises.push(mod.Inst.init())
}
await Promise.all(promises)
console.log("ModuleMgr")
}
public release(){
console.log("ModuleMgr onRelease")
for(let mod of this.modules.reverse()){
mod.release()
}
this.modules.length=0
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "8e11150f-b79e-41e3-b05f-05edc4192642",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
import Manager from "./Manager";
import AppFacade from "../AppFacade";
import AssetMgr from "./AssetMgr";
import { ResConst } from "../ConstDefine/ResConst";
import LoopMgr from "./LoopMgr";
import MathUtil from "../Util/MathUtil";
import GameUtil from "../Util/GameUtil";
import { EventConst } from "../ConstDefine/EventConst";
const ValidID=-1
class Info{
constructor(public res: string, public Id: number = ValidID, public loop: boolean = true, public volume: number = 1) { }
}
export default class SoundMgr extends Manager{
static get TypeName(): string{return "SoundMgr"}
private musicDic:Map<string,Info>=new Map()
private effectDic:Map<string,Info>=new Map()
private tmpMusic:Info
private effectResDic:Map<string,cc.AudioClip>=new Map()
async start(){
this.initSoundDB()
this.playStartMusic()
console.log("SoundMgr")
cc.systemEvent.on(EventConst.ShowGame,this.onShowGame,this)
cc.systemEvent.on(EventConst.HideGame,this.onHideGame,this)
}
public release(){
console.log("SoundMgr onRelease")
this.stopAllMusic()
this.stopTmpMusic()
this.musicDic.clear()
this.effectResDic.clear()
this.tmpMusic=undefined
cc.systemEvent.off(EventConst.ShowGame,this.onShowGame,this)
cc.systemEvent.off(EventConst.HideGame,this.onHideGame,this)
}
private onHideGame(){
cc.log("cocos隐藏游戏")
// cc.audioEngine.pauseAll()
}
private onShowGame(){
cc.log("cocos显示游戏")
// cc.audioEngine.resumeAll()
}
private initSoundDB() {
}
private playStartMusic(){
}
public tryChangeMusic(isOpen:boolean){
cc.log("改变声音状态",isOpen)
if(isOpen){
// this.IsMusicOpen&&this.resumAllMusic()
cc.audioEngine.resumeAll()
}else{
cc.audioEngine.pauseAll()
}
}
//播放URL的音乐
public async playMusicByUrl(resName: string, volume: number = 1, loop: boolean = true) {
let info: Info = this.musicDic.get(resName)
if (!info) {
info = new Info(resName)
//不循环的没必要加如缓存
loop && this.musicDic.set(resName, info)
info.loop = loop
info.volume = volume
}
let audio = await this.loadResByUrl(resName) as cc.AudioClip;
if (audio) {
info.Id = cc.audioEngine.play(audio, loop, volume)
cc.log("播放音乐", resName)
}
}
//播放场景中的音乐
public async playResMusic(resName:string,volume:number=1,loop:boolean=true){
let info:Info=this.musicDic.get(resName)
if(!info){
info=new Info(resName)
//不循环的没必要加如缓存
loop&&this.musicDic.set(resName,info)
info.loop=loop
info.volume=volume
}
let audio = this.loadResClone(resName);
if (audio) {
info.Id = cc.audioEngine.play(audio, loop, volume)
cc.log("播放音乐", resName)
}
}
/**
* 播放音乐,可以同时播放多个音乐
* @param resName
* @param volume
* @param loop
*/
public async playMusic(resName:string,volume:number=1,loop:boolean=true){
let info:Info=this.musicDic.get(resName)
if(!info){
info=new Info(resName)
//不循环的没必要加如缓存
loop&&this.musicDic.set(resName,info)
info.loop=loop
info.volume=volume
}
let audio = await this.loadResAsync(ResConst.AudioABName, resName)
if (audio) {
info.Id = cc.audioEngine.play(audio, loop, volume)
cc.log("播放音乐", resName)
}
}
/**
* 播放临时音乐,不会被记录下来musicDic
* @param resName
* @param volume
* @param loop
* @param resume 播放结束自动切回背景音乐吗
*/
public async playTmpMusic(resName:string,volume:number=1,loop:boolean=true,resume:boolean=false){
if(this.tmpMusic){
this.stopTmpMusic()
}
this.tmpMusic=new Info(resName)
let audio=await this.loadResAsync(ResConst.AudioABName,"Bgm/"+resName)
let musicTime=0
if(audio){
this.tmpMusic.loop=loop
this.tmpMusic.volume=volume
this.tmpMusic.Id=cc.audioEngine.play(audio,loop,volume)
musicTime=audio.duration
}
if(resume&&musicTime>0){
AppFacade.getMgr(LoopMgr).setTimeout(()=>{
this.resumAllMusic()
},musicTime)
}
}
public stopTmpMusic(){
if(!this.tmpMusic) return
if(this.tmpMusic.Id!=ValidID){
cc.audioEngine.stop(this.tmpMusic.Id)
}
this.tmpMusic=null
}
public async resumAllMusic(){
for(let v of this.musicDic){
let info=v[1]
await this.playMusic(info.res,info.volume,info.loop)
}
}
public stopAllMusic(){
cc.audioEngine.stopAll()
}
public stopMusic(resName:string){
let info = this.musicDic.get(resName)
this.musicDic.delete(resName)
if(info&&info.Id!=ValidID){
cc.audioEngine.stop(info.Id)
}
}
//一套音效随机播放一个
public playEffectR(resName:string[],volume:number=1){
let i=MathUtil.randInt(resName.length)
this.playEffect(resName[i],0,volume)
}
public playEffect(resName:string,delay:number=0,volume:number=1,isLoop:boolean=false){
if(GameUtil.isStringEmpty(resName)) return
if (delay > 0) {
AppFacade.getMgr(LoopMgr).setTimeout(this._playEffect.bind(this, resName, volume), delay)
} else {
this._playEffect(resName, volume, isLoop)
}
}
public stopEffect(resName:string){
if(GameUtil.isStringEmpty(resName)) return
let info=this.effectDic.get(resName)
if(info){
cc.audioEngine.stopEffect(info.Id)
this.effectDic.delete(resName)
}
}
//播放URL的音效
public async playEffectByUrl(resName: string, delay: number = 0, volume: number = 1, isLoop: boolean = false) {
let audio = await this.loadResEffectByUrl(resName)
if (audio) {
let id = cc.audioEngine.play(audio, isLoop, volume)
//长期循环播放才保存
if (isLoop) {
let info = new Info(resName, id, isLoop, volume)
this.effectDic.set(resName, info)
}
}
}
//播放场景中的音效
public playResEffect(resName:string,delay:number=0,volume:number=1,isLoop:boolean=false){
let audio=this.loadResEffectClone(resName)
if(audio){
let id=cc.audioEngine.play(audio,isLoop,volume)
//长期循环播放才保存
if(isLoop){
let info=new Info(resName,id,isLoop,volume)
this.effectDic.set(resName,info)
}
}
}
private async _playEffect(resName:string,volume:number=1,isLoop:boolean=false){
let audio=await this.loadEffectAsync(resName)
if(audio){
let id=cc.audioEngine.play(audio,isLoop,volume)
//长期循环播放才保存
if(isLoop){
let info=new Info(resName,id,isLoop,volume)
this.effectDic.set(resName,info)
}
}
}
private async loadResEffectByUrl(resName:string){
let effect=this.effectResDic.get(resName)
if(!effect){
effect=await this.loadResByUrl(resName) as cc.AudioClip;
effect&&this.effectResDic.set(resName,effect)
}
return effect
}
private loadResEffectClone(resName:string){
let effect=this.effectResDic.get(resName)
if(!effect){
effect=this.loadResClone(resName)
effect&&this.effectResDic.set(resName,effect)
}
return effect
}
private async loadEffectAsync(resName:string){
let effect=this.effectResDic.get(resName)
if(!effect){
effect=await this.loadResAsync(ResConst.AudioABName,resName)
effect&&this.effectResDic.set(resName,effect)
}
return effect
}
private async loadResAsync(abName:string,resName:string):Promise<cc.AudioClip>{
let asMgr=AppFacade.getMgr(AssetMgr)
return await asMgr.loadAssetAsync<cc.AudioClip>(abName,resName,cc.AudioClip)
}
private loadResClone(resName:string,instantiate:boolean=false){
let prefab=cc.find(ResConst.AudioABName+"/"+resName);
if (!prefab) {
console.error("loadViewClone prefab is null")
return
}
let clone = instantiate && cc.instantiate(prefab) || prefab
return clone.getComponent(cc.AudioSource).clip;
}
private async loadResByUrl(resName:string){
return new Promise((resolve,reject)=>{
if(!resName){
reject("文件名错误!");
}
cc.assetManager.loadRemote(resName, (err, audioClip) => {
resolve(audioClip);
});
});
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment