cocos creator 项目总结四(游戏启动流程设计)

        由于creator是针对 android、ios、web、小游戏等平台的引擎,所以游戏的加载过程肯定是要能适应各个环境的启动的。对于web和小游戏这种需要远程下载资源的肯定是要做好启动流程的设计这对于游戏的启动速度效果是有很重要效果的。

        在指定启动流程的时候首先要提到的是creator bundle模式的一个特点,就是bundle如果选择了小游戏的 subpackage 模式就不能让资源是 remoteassets 了,如果设置成了 remoteasset 那你的代码就只能是在主包里的,这里就涉及到一个问题,就是我们游戏引擎的代码打包出来就已经接近了4Mb,如果我们的业务代码不分包就发布不了超出了小游戏的限制。所以我们设计的时候业务代码肯定是最好做成分包。另外跨bundle包引用代码必须要先加载bundle包,否则就会有问题(如果你目前没问题,那你打包个包就有问题了,因为直接运行是没问题的,别问我为什么知道的,因为我踩坑了。)

        所以针对上面的特性,我的建议是我们同一个模块的代码和资源一定要分不同的目录管理。

然后单独一个bundle用于启动整个游戏,这个bundle 尽量的精简,只要一个背景图片,一个加载脚本就足够了。然后再这个加载脚本将游戏必要的资源bundle包,代码bundle包都加载好,然后再加载登录场景中的启动prefab, 在prefab上绑定一个启动的脚本。这么做主要是跨包引用代码会造成报错,因为我的启动脚本不能依赖其它的代码,只能通过动态加载prefab避免这个问题。

如下是我的启动bundle包


import * as cc from 'cc';
import { BaseLoader } from './BaseLoader';
const { ccclass, property } = cc._decorator;

enum ENV {
    DEBUG,
    INNER_TEST,
    OUT_TEST,
    RELEASE,
}

@ccclass('Lauch')
export class Lauch extends cc.Component {
    @property(cc.ProgressBar)
    private m_loadingBar : cc.ProgressBar = null!;

    @property(cc.Label)
    private m_lblProcess : cc.Label = null!;

    @property({
        type : cc.Enum(ENV),
        displayName : "GameEnv",
        tooltip : "游戏发布环境",
    })
    private m_gameEnv : number = ENV.RELEASE;


    updateProcess(percent : number){
        this.m_lblProcess.string = `游戏加载中:${percent}%`
        this.m_loadingBar.progress = percent/100;
    }

    start () {
        let resload = new BaseLoader();
        this.updateProcess(0);
        
        cc.setDisplayStats(this.m_gameEnv != ENV.RELEASE);
        
        BaseLoader.loadBundleArray(["modules"], ()=>{
            resload.loadPrefab("modules#world/GameWorld", ( err, prefab : cc.Prefab)=>{
                let node = cc.instantiate(prefab);
                let GameWorld : any = node.getComponent("GameWorld");
                GameWorld.m_loadingBar = this.m_loadingBar;
                GameWorld.m_lblProcess = this.m_lblProcess;
                GameWorld.m_gameEnv = this.m_gameEnv;
                cc.game.addPersistRootNode(node);
            })
        }, ( percent : number)=>{
            this.updateProcess(Math.floor(percent*100));
        })
    }
}

// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import * as cc from 'cc';
import { ENV, setCurEnv} from "../base/config/Env"
import { SceneMgr } from '../base/core/SceneMgr';
import { Network } from '../base/net/Network';
import { log}  from "../base/log/log"
import { utils } from '../base/utils/utils';
import { platform } from '../base/platform/platform';
import { EventDispatcher, EventType, ListenerFunc, EventListener } from '../base/frame/EventDispatcher';
import { ResLoader, SoundMgr } from '../base/core';
import { BundleAsset } from '../../world/BaseLoader';
import { ConfigService } from '../common/src/ConfigService';

const { ccclass, property } = cc._decorator;

export const enum GlobalEvent{
    UPDATE_FINISH,
    UPDATE_PROCESS,
    UPDATE_NEED_UPDATE,
    UPDATE_ERROR,
    INIT_UPDATE_MANIFEST,
}

@ccclass('GameWorld')
export class GameWorld extends cc.Component {
    private static s_instance : GameWorld | null = null;
    
    public static getInstance() : GameWorld{
        if(this.s_instance == null){
            this.s_instance = new GameWorld();
        }

        return this.s_instance;
    }

    private m_audioSource : cc.AudioSource | null = null;
    private m_eventDispatcher : EventDispatcher = new EventDispatcher();

    public m_gameEnv : ENV = null!;

    @property({
        displayName : "是否开启广告", 
    })
    private m_openAd : boolean = true;

    @property({
        displayName: "广告跳过提示",
        visible(){
            let obj : any = this;
            return !obj.m_openAd;
        },
    })
    private m_filterAdTips : string = "广告尚未接入,当前直接跳过广告!";


    public m_loadingBar : cc.ProgressBar = null!;
    public m_lblProcess : cc.Label = null!;
    public m_globalResLoader : ResLoader = new ResLoader();

    getAudioSource() : cc.AudioSource | null
    {
        return this.m_audioSource;
    }


    getGlobalResLoader() : ResLoader{
        return this.m_globalResLoader;
    }

    getCurEnv() : ENV{
        return this.m_gameEnv;
    }

    getIsOpenAd():boolean{
        return this.m_openAd;
    }

    getFilterAdTips():string{
        return this.m_filterAdTips;
    }

    initResourceSize(){
        let framesize = cc.view.getFrameSize();
        let mysize = cc.size(1334, 750);

        let ftmp = framesize.width/framesize.height;
        let rtmp = mysize.width/mysize.height;

        let resolutionSize = cc.size(1334, 750);
        if( ftmp > rtmp ){
            resolutionSize.height = mysize.height;
            resolutionSize.width = resolutionSize.height * framesize.width/framesize.height;
            
        }else{
            resolutionSize.width = mysize.width;
            resolutionSize.height = resolutionSize.width * framesize.height/framesize.width;  
        }
        cc.view.setDesignResolutionSize(resolutionSize.width, resolutionSize.height, cc.ResolutionPolicy.SHOW_ALL);
    }

    onLoad()
    {
        this.initResourceSize();

        this.m_audioSource = this.getComponent(cc.AudioSource);
        cc.assert(this.m_audioSource, "must add Component cc.AudioSource in GameWorld Node");
        console.log("GameWorld cur env", this.m_gameEnv);
        setCurEnv(this.m_gameEnv);

        if(GameWorld.s_instance == null)
        {
            GameWorld.s_instance = this;
        }
        else
        {
            console.error("Gameworld is repeat load!");
        }

        cc.game.on(cc.Game.EVENT_HIDE, ()=>{
            //游戏切后台
            console.log("EVENT_GAME_HIDE")            
            SoundMgr.getInstance().pauseMusic();
        })

        cc.game.on(cc.Game.EVENT_SHOW, ()=>{
            //游戏切前台
            console.log("EVENT_GAME_SHOW");
            this.scheduleOnce(()=>{
                SoundMgr.getInstance().resumeMusic();
            }, 0.1)
        })
    }

    public addListenerOnce(event : EventType,  owner : Object, handler : ListenerFunc,) : EventListener {
        return this.m_eventDispatcher.addListenerOnce(event, owner, handler);
    }

    public addListener( event : EventType, owner : Object, handler : ListenerFunc,  count : number = -1, order : number = 0) : EventListener {
        return this.m_eventDispatcher.addListener(event, owner, handler, count, order);
    }

    public pauseListenerByOwner( owner : Object, event ?: EventType){
        return this.m_eventDispatcher.pauseListenerByOwner(owner, event);
    }
    
    public resumeOwner(owner : Object, event ?: EventType){
        return this.m_eventDispatcher.resumeOwner(owner, event);
    }

    public removeListenerByOwner( owner : Object, event ?: EventType){
        return this.m_eventDispatcher.removeListenerByOwner(owner, event);
    }

    public removeListenerByEvent( event : EventType){
        return this.m_eventDispatcher.removeListenerByEvent(event);
    }

    public removeListener( event : EventType,  owner : Object, handler : ListenerFunc){
        return this.m_eventDispatcher.removeListener(event, owner, handler);
    }

    public dispatch( event : EventType, ...datas : any[]) {
        return this.m_eventDispatcher.dispatch(event, ...datas);
    }

    public addListenerAll(owner : Object, func : ListenerFunc){
        return this.m_eventDispatcher.addListenerAll(owner, func);
    }

    public removeListenerAll(owner : Object, func : ListenerFunc){
        return this.m_eventDispatcher.removeListenerAll(owner, func);
    }

    public initUpdateManifest( doneCallback : ()=>void){
        if( cc.sys.isNative ){
            this.getGlobalResLoader().LoadAsset("project", ( err, asset : cc.Asset )=>{
                console.log("initUpdateManifest result project", );
                this.dispatch(GlobalEvent.INIT_UPDATE_MANIFEST, asset);
                doneCallback()
            })
        }else{
            doneCallback();
        }
    }

    start () {
        let global : any = globalThis;
        global.utils = utils;
        global.log = log;
        global.SoundMgr = SoundMgr;

        
        console.log(utils.parseGetParams());
        log.d("gameWorld start", cc.sys);
        log.d("os", cc.sys.os, cc.sys.isBrowser);
        log.d("platform", cc.sys.platform);
        platform.getInstance().init()
        this.initUpdateManifest(()=>{
            Network.getInstance().init(()=>{
                this.launchGame();
            })
        })
    }

    update(dt: number){
        Network.getInstance().update(dt);
    }

    restartGame(){
        platform.getInstance().restart();
    }
    
    launchGame(){
        this.m_loadingBar.progress = 0;
        this.m_lblProcess.string = `加载bundle资源中 0%`

        ResLoader.loadBundleArray(["modules", "common"], ( err : Error | null, bundles : Map<string, BundleAsset> | null )=>{
            if(bundles){
                bundles.forEach(( bundle )=>{
                    bundle.addRef(); //全局报不需要释放
                })
            }
            this.m_loadingBar.progress = 0;
            this.m_lblProcess.string = `加载配置表资源中 0%`

            ConfigService.getInstance().loadAllConfigs(()=>{
                this.m_loadingBar.progress = 0;
                this.m_lblProcess.string = `加载场景中 0%`
                SceneMgr.getInstance().loadRunScene("login#loginScene", ()=>{
                    
                }, ( percent : number)=>{
                    this.m_loadingBar.progress = percent;
                    this.m_lblProcess.string = `加载场景中 ${Math.floor(percent*1000)/10}%`
                })
            }, ( percent : number)=>{
                this.m_loadingBar.progress = percent;
                this.m_lblProcess.string = `加载配置表资源中 ${Math.floor(percent*1000)/10}%`
            })
        })
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Cocos Creator是一款集成化游戏开发工具,它可以帮助开发者快速构建游戏Cocos Creator框架文档就是为这个工具而设计的,它详细介绍了框架的各个方面: 1.游戏组件: Cocos Creator游戏组件是构成游戏逻辑的基本单位,如:精灵,动画,音效,等等。框架文档详细介绍了这些游戏组件的实现方式和使用方法。 2.游戏场景: 场景是游戏不可或缺的一部分,游戏场景的绘制、布局、切换等功能在Cocos Creator的实现方式和使用方法也被框架文档详细介绍了。 3.游戏节点管理: Cocos Creator管理游戏节点的方式是通过层次结构进行管理,框架文档详细介绍了如何使用节点管理器来组织游戏节点。 4.贴图管理: 游戏的图片资源在Cocos Creator管理方式与其他游戏开发工具略有不同,框架文档详细介绍了如何使用贴图管理器来管理游戏的图片资源,以及如何使用它们。 5.数据存储: 在游戏开发过程,需要存储很多游戏数据,Cocos Creator提供了一套数据存储方案,框架文档详细介绍了如何使用数据存储器来存储、读取数据。 总之,框架文档为开发者提供了一个非常完整的Cocos Creator游戏开发体验,帮助开发者更好、更快地完成游戏开发工作。 ### 回答2: Cocoscreator是一款广泛使用的游戏开发工具,它支持多种平台,包括Web、iOS、Android等。针对这款工具,设计游戏框架文档是非常必要的。 游戏框架文档是对游戏开发使用到的各种类、接口、函数等进行的系统化整理和说明,旨在帮助开发人员更加快速、高效地完成游戏的开发。针对cocoscreator,要编写的游戏框架文档必须包括以下内容: 1.场景和节点 这是cocoscreator的核心组成部分,开发人员应该了解和掌握它们的使用方法。文档可以详细介绍场景、节点的作用、属性和接口等,以及它们在开发过程的使用场景和注意事项。 2.资源管理 在游戏开发,资源管理是非常重要的,它关系到游戏的加载速度和性能。因此,游戏框架文档应该对资源加载、复用、释放等方面进行详细说明。 3.事件处理 事件处理是cocoscreator的另一大特色,文档应该详细说明事件的相关接口和使用方法,包括监听事件、派发事件等。 4.动画和动作 cocoscreator提供了丰富的动画和动作接口,可以制作出生动、有趣的游戏效果。文档应该详细介绍动画和动作的使用方法和属性等。 5.游戏逻辑和交互 游戏逻辑和交互是游戏的核心部分,文档应该对游戏逻辑和交互流程进行详细说明,以及说明与其他模块的关联和调用方式。 综上所述,设计cocoscreator游戏框架文档对游戏开发至关重要,只有编写出清晰、详尽的文档,才能帮助开发人员快速完成游戏开发,提高开发效率和游戏质量。 ### 回答3: Cocoscreator是一款非常强大的游戏开发引擎,它使用的是JavaScript语言进行编写。设计一款优秀的游戏框架,是成功开发一款游戏的重要因素之一。 Cocoscreator游戏框架文档包含以下几个方面的内容: 1.场景管理器 场景管理器是整个游戏框架的核心部分,它主要负责游戏场景的管理。在这里可以创建新的场景、进入到不同的场景,以及场景之间的传递和切换。 2.游戏控制器 游戏控制器主要负责控制游戏逻辑,包括游戏运行时的场景、角色、道具等元素的控制和管理。它可以控制游戏的开始、暂停、继续、结束等操作。 3.角色控制器 角色控制器负责游戏所有角色的控制和管理。它可以控制角色的移动、攻击、受伤、死亡以及角色之间的互动。 4.界面管理器 界面管理器主要负责游戏所有界面的管理。界面是游戏很重要的组成部分,它可以控制游戏的暂停、结束、返回主菜单等操作。 5.音效管理器 音效管理器负责游戏所有音效的管理。在游戏添加适当的音效可以增强游戏的娱乐性和吸引力,让游戏更加生动和有趣。 这些功能的协同工作,共同构成了一款成功的游戏框架。通过Cocoscreator游戏框架文档,我们可以更加系统和高效地进行游戏开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值