美文网首页一只腊鸭做游戏
决战-Pow!第一集:插件管理

决战-Pow!第一集:插件管理

作者: 回忆并快 | 来源:发表于2018-01-30 02:17 被阅读13次

在开发游戏之前,做好准备,将会大大降低之后或者日后开发一款新的小游戏所花费的时间。
因此开发一个灵活简单通用的框架必不可少。
第一集,给大家带来的是插件系统这个简单的模块化管理。

为何,在这里没有采取puremvc类似的ts框架?
原因很简单,过于注重MVC会影响灵活性,而且不一定容易让别人上手,当然这些都是个人选择了,我觉得这么开发效率高,而且思路清晰,就使这个插件系统了。

插件管理:
这是一个简单的插件系统关系图。


UML

1.建立一个基类BasePlugin来作为上层接口和功能提供,它继承于Laya.EventDipatcher,方便交流和流程处理。
2.我们所有的模块Plugin均继承于BasePlugin,进行各自功能开发。
3.单例PluginManager,把这些插件管理起来,然后Plugin可以通过这样一个管理器,进行交流,加载,卸载等。
4.Controller这部分就由这部分组成,至于MV的部分,后面会各自建立,然后再把这三大块串联起来。

是不是非常简单?
大家只要开发和管理自己的插件,并且按照约定的插件使用方法,就不容易影响别人开发。

举个栗子:
如果我现在有一个战斗模块,需要用到背包数据,获取用户信息,使用输入模块。我就可以通过一个配置把这些插件和数据组合起来和使用,很方便,至于View是不能影响我们的逻辑模块的,它只会受数据的变化。

此插件系统,是基于Laya.EventDispatcher和我之前文章中的数据结构库开发

PluginManager.ts

class PluginManager extends Laya.EventDispatcher {
    private _plugins: Dictionary<string, BasePlugin> =  new Dictionary<string, BasePlugin>();
    private static _instance: PluginManager = null;
    constructor() {
        super();
    }
    public static getInstance(): PluginManager {
        return this._instance || (this._instance = new this());
    }

    public initialize(): void {
        this.addPlugin(new LoginPlugin()).init();
    }

    public openPlugin(pluginName:string, closeAll:boolean = true, data?:any):void{
        if(closeAll){
            this.closeAllPlugins();
        }
        let plugin:BasePlugin = this.getPlugin(pluginName);
        if(plugin != null){
            plugin.open(data);
        }
    }

    public closePlugin(pluginName:string):void{
        let plugin:BasePlugin = this.getPlugin(pluginName);
        if(plugin != null){
            plugin.close();
        }
    }

    public closeAllPlugins():void{
        for (let pair of this._plugins){
            if(pair.value != null){
                (pair.value as BasePlugin).close();
            }
        }
    }

    public addPlugin(plugin: any): BasePlugin {
        let pluginName: string = plugin.name;
        if (this._plugins.containsKeyValue(pluginName)) {
            Logger.log(`plugin ${pluginName} is exists.`);
            return this._plugins.get(pluginName);
        }
        this._plugins.addKeyValue(pluginName, plugin)
        return plugin;
    }

    public removePlugin(pluginName: string): void {
        let plugin: BasePlugin = this._plugins.get(pluginName);
        if (plugin != null) {
            Logger.log(`plugin ${pluginName} is no exists, cant remove.`);
            return;
        }
        this._plugins.removeKeyValue(pluginName);
    }

    public getPlugin(pluginName: string): BasePlugin {
        return this._plugins.get(pluginName);
    }

    public removePlugins(): void {
        this._plugins.clear();
    }
}

BasePlugin.ts

class BasePlugin extends Laya.EventDispatcher {
    constructor() {
        super();
    }
    public init() {
        // Logger.log("BasePlugin init");
    }
    public load(assets?:any) {
        if(assets !== null){
            Laya.loader.load(assets, Handler.create(this, this.onComplete), Handler.create(this, this.onProgress, null, false));
        }
    }
    private onComplete(){
        this.dispatchEvent(PluginEvent.COMPLETE);
    }
    private onProgress(ratio:number){
        let progress:number = Math.floor(ratio*100);
        this.dispatchEvent(PluginEvent.PROGRESS, progress);
    }
    public unload() {
        // Logger.log("BasePlugin unload");
    }
    public open(data?:any) {
        // Logger.log("BasePlugin open");
    }
    public close() {
        // Logger.log("BasePlugin close");
    }
    public get name(){
        return this.constructor.name;
    }

    protected _handlerDict:Dictionary<number, Handler> = new Dictionary<number, Handler>();
    public registerHandler(cmd:number, handler:Handler){
        if(this._handlerDict.containsKeyValue(cmd)){
            return;
        }
        this._handlerDict.addKeyValue(cmd, handler);
    }

    public async sendReq(cmd:number, req:any) {
        let res:any = await this.testSend();
        let handler:Handler = this._handlerDict.get(cmd);
        if(handler !== null){
            handler.runWith([cmd, res, req]);
        }
    }

    // 发送事件
    public dispatchEvent(type:string, data?:any){
        this.event(type, data);
    }
}

LoginPlugin.ts

class LoginPlugin extends BasePlugin {
    constructor() {
        super();
    }
    private _createTime:number = 0;
    public open() {
        // 登录界面
        let page:LoginPage = UIManager.getInstance().openPage(LoginPage);
        page.pow.play();
    }
    public close() {
        Logger.log("close");
        UICommon.closeLoading();
        UIManager.getInstance().closePage(LoginPage);
    }
    public login(id:number, name:string, pwd:string):void{
        let ud:UserData = new UserData();
        ud.id = id;
        ud.name = name;
        ud.powid = 1;
        this.sendReq(1, ud);
    }
    public init() {
        this.registerHandler(1, Handler.create(this, this.onResLogin));
    }
    public onResLogin(cmd:number, res:any, req:any){
        Logger.log("登录成功");
    }
}

拿了个LoginPlugin作为例子。
此处还带有的额外的知识:
简单的Logger(其实暂时没做些什么,只是打上了个标识)

class Logger{
    public static log(...args){
        console.log(`[DEBUG INFO] `, ...args);
    }
}

ts单例写法

private static _instance: PluginManager = null;
public static getInstance(): PluginManager {
   return this._instance || (this._instance = new this());
}

不知不觉写到现在,今晚就写到这,希望能对你有点启发,或者有何不妥之处,不吝交流~

相关文章

网友评论

本文标题:决战-Pow!第一集:插件管理

本文链接:https://www.haomeiwen.com/subject/qtlqzxtx.html