查看: 4191|回复: 3

[原创发布] 我又来发脚本了_这次发布的是一个 游戏流程管理插件

[复制链接]
梦石
0
星屑
50
在线时间
56 小时
注册时间
2016-3-23
回帖
13
发表于 2016-4-3 23:12:22 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 大钊 于 2016-4-3 23:17 编辑

大家好啊,我是之前发 编辑大量对话的插件 和 拆分代码的工具 的新人。
这次我又来发脚本了。

我不知道大家是怎么管理游戏的流程的啊。。。
我最开始是设置了几个变量和开关来管理流程。。但序章都没写完就管理不过来了。。。经常一个事件要判断N个变量+N个开关。。。又不能用复合条件,全靠if来套。。。整个事件流搞得难看得要死。。。
所以就搞了这个插件。。。

先简单说说使用方法吧:
导入插件:
注意,本插件和我之前发的消息插件一样,也依赖 "LYZ_Core" 这个插件,。或者说我的个人插件都会依赖这个。
QQ截图20160403210501.png

几个参数:
"Flow Tree Definition"是文件名,文件放在"data/FLOW"文件夹下:
QQ截图20160403210551.png
Tab Indent,几个tab算作一次缩进。
Space Indent,几个空格算作一次缩进
缩进是用来判定这是哪一级流程的,非常重要。
Max Depth是表示流程树有多深,默认为8层,虽然我至今最多只用到了3层。

然后光说参数含义还是肯定懂不了,所以再来说说流程定义文件。长这样。
[pre lang="text"]
第一卷
        第一章
                事件1
                事件2
                事件3
        第二章
                事件1
                事件2
                事件3
        第三章
                事件1
                事件2
                事件3
第二卷
        第一章
                事件1
                事件2
                事件3
        第二章
                事件1
                事件2
                事件3
        第三章
                事件1
                事件2
                事件3
[/pre]
很典型的树状结构。缩排就是用来表示流程级别的。比如第一卷第二卷是一级流程,第一章第二章之类是二级流程,事件1事件2之类是三级流程,
郑重提醒,缩排用的格式最好全文件统一,用tab就全用tab,用空格就全用空格,混用特别容易出错。
深度就是最多有几级流程,比如现在这个流程树深度为3。
所有流程都不允许以'$'开头,有可能会跟保留字段冲突。

占位流程($):每一级流程之前都有一个名为'$'的流程,在没有设置子流程之前用于占位之用。
流程的值(.$value):每个流程会被自动分配一个值,从上到下依次增加,占位流程的值与父流程相同。
举个栗子,还是拿上面的流程树来说:
这代码里面Flow是根流程,所有一级流程都是它的子流程
[pre lang="javascript"]
Flow.第一卷.$value==1
Flow.第一卷.第一章.$value==2
Flow.第一卷.第一章.事件1.$value==3
Flow.第一卷.第一章.事件2.$value==4
Flow.第一卷.第二章.$value==6
Flow.第一卷.第二章.事件3.$value==9
Flow.第二卷.$value==14
Flow.第二卷.第二章.事件3.$value==22
Flow.$.$value==0
Flow.$.$.$.$value==0
Flow.第一卷.$.$value==1
Flow.第一卷.$.$.$value==1
Flow.第一卷.第二章.事件3.$.$.$.$value==9
[/pre]
以此类推

常用语句:
[pre lang="javascript"]
Flow.XX卷.XX章.XX事件 //获取指定流程对象
Flow() /*或*/ Flow.$Current //可以获取当前所在流程对象
//流程对象可以使用以下函数(流程b参数可以省略,省略则视为带入了Flow.$Current)
流程a.$eq(流程b) /*或*/ 流程a.$is(流程b) //比较两个流程是否相同
流程a.$lt(流程b) /*或*/ 流程a.$before(流程b) //判断流程a是否在b流程之前
流程a.$gt(流程b) /*或*/ 流程a.$after(流程b)//判断流程a是否在b流程之后
流程a.$le(流程b) /*或*/ 流程a.$ngt(流程b) //判断流程a是否在b流程之前或者相同
流程a.$ge(流程b)/*或*/ 流程a.$nlt(流程b) //判断流程a是否在b流程之前或者相同
流程a.$ne(流程b) /*或*/ 流程a.$neq(流程b) //比较两个流程是否相同
流程a.$in(流程b) //判断流程a是不是流程b的子流程(包括直接和间接)
流程a.$contains(流程b)//判断流程a是不是流程b的父流程(包括直接和间接)
流程.$value /*或*/ 流程.$val 或 流程.$v //获取流程的值。如上面解释的。觉得上面的函数难看的话可以用 流程 "a.$v==流程b.$v"之类的语句来进行流程判定。
流程.$index /*或*/ 流程.$i //获取该流程是福父流程的第几个流程,占位流程为0,正式流程从1开始。
流程.$chilren //获取该流程的所有子流程。
流程.子流程名字  /*或*/ 流程['子流程名字'] //直接获取指定子流程,'Flow.XX卷.XX章.XX事件'即为此语句的串联用法
Flow[ i ] //获取当第i级流程,i=0时会获取到根流程
Flow[ i ]='流程名' //设置当前第i级流程,必须是Flow[i-1]的子流程才会成功,i不允许为0
[/pre]

还有很多高级用法说不完,下面就是定义流程对象类型的代码片段,愿意的自己可以啃代码;
[fold=Chapter类][pre lang="javascript"]class Chapter{
        constructor(parent,name,level,index){
            this.$_init(parent,name,level,index);
        }

        $_init(parent,name,level,index){
            var _this=this;
            this["$valueCounter"]=0;
            this["$parent"]=parent;
            this["$name"]=name;
            this["$value"]=index==0&&parent!=null?parent.$value:this.$root.$valueCounter++;
            this["$index"]=index;
            this["$level"]=level;
            this["$desc"]="Chapter %1: %2  (%3)".format(this.$value,this.$fullName, this.$root.$key);
            if (this.$level<maxDepth) this.$add("$");
        }

        $_adaptArg(o){
            if (o==null) o=this.$root.$Current;
            if (o instanceof Chapter) o= o.$v;
            var n=Number(o);
            if (n==null||Number.isNaN(n)) throw "invalid arg: '"+o+"'";
            return n;
        }

        $add(name){
            if (this["$children"]==null) this["$children"]=[];
            var chapter=new Chapter(this,name,this.$level+1,this.$children.length);
            this.$children.push(chapter);
            this[name]=chapter;
            if (this.$firstChild==null){
                this.$firstChild=this.$lastChild=chapter;
            }else{
                this.$lastChild.$next=chapter;
                chapter.$prev=this.$lastChild;
                this.$lastChild=chapter;
            }
            return chapter;
        }

        $eq(o){ return this.$value==this.$_adaptArg(o); }
        $gt(o){ return this.$value>this.$_adaptArg(o); }
        $ne(o){ return !this.$eq(o); };
        $lt(o){ return this.$value<this.$_adaptArg(o); };
        $ge(o){ return this.$gt(o)||this.$eq(o); };
        $le(o){ return this.$lt(o)||this.$eq(o); };
        $contains(o){var nv=this.$nextValid;return this.$le(o)&&(nv==null||nv.$gt(o));};
        $in(o){var nv=this.$root.$byValue[this.$_adaptArg(o)].$nextValid;return c.$le(this)&&(nv==null||nv.$gt(this));};

        get $fullName(){return this.$parent?this.$parent.$fullName+"."+this.$name:""}
        get $root(){return this.$parent?this.$parent.$root:this;};
        get $nextValid(){return this.$next||(this.$parent?this.$parent.$nextValid:null);}
        get $ceil(){var nv=this.$nextValid;return nv?nv.$value:this.$root.$byValue.length;};
        get $deepest(){ return this.$firstChild==null?this:this.$firstChild.$deepest;};
        get $mostShallow(){return (this.$parent&&this.$parent.$value==this.$value)?this.$parent.$mostShallow:this;};
    }
    $.alias(Chapter.prototype,"$eq","$is");
    $.alias(Chapter.prototype,"$gt","$after");
    $.alias(Chapter.prototype,"$ne","$neq","$not");
    $.alias(Chapter.prototype,"$lt","$before");
    $.alias(Chapter.prototype,"$ge","$nlt");
    $.alias(Chapter.prototype,"$le","$ngt");
    $.alias(Chapter.prototype,"$value","$v","$val");
    $.alias(Chapter.prototype,"$index","$i");[/pre][/fold]

这些语句都知道了,在哪用呢:
主要是两个地方:判断流程和设置流程
QQ截图20160403221337.png
QQ截图20160403221357.png
判定(Flow的F大写):
QQ截图20160403222405.png
设置(插件指令和脚本均可,区别只是脚本只能F大写,插件指令F大小写均可):
QQ截图20160403222455.png
QQ截图20160403222532.png
因为是脚本,所以均支持复合条件判定
比如 Flow.第一卷.$contains() || Flow.第二卷第四章.$is()
或者 Flow.第一卷.第一章.$lt() && Flow.第二卷第四章.$gt()

另外关于如何判断游戏开始。
游戏第一次进入时所在的流程是$.$.$.$......值为0
所以可以像我图中那样用Flow().$v==0来判定,也可以用Flow.$is()来判定,第二种更简洁,第一种语义更明确,用哪种看喜好。

流程发生切换的时候会自动在控制台打log方便调试。
QQ截图20160403223722.png

当前所在流程会被存档,读档时是根据名字进行索引的,所以如果只是改了流程顺序或者增加了流程存档仍然可用,但如果流程改了名字或者删除了流程,进度刚好在被改名或者删除的流程位置的存档会失效。

其他:
Flow对象是插件定义在全局对象上的属性,如果发生命名冲突可以通过LYZ.Flow或者LYZ.FlowManager.Flows['Main']来访问这个对象。
插件默认只创建了一个全局流程管理对象(即Flow对象),用于管理整个游戏的流程
但是可以用LYZ.FlowManager.MakeFlow(filename,key)来创建新的流程管理对象,每个对象各自独立。可以通过返回值或者LYZ.FlowManager.Flows[key]来获取这个对象。
比如如果会写脚本的话可以将这东西附着在任务对象上,让任务系统也拥有流程管理能力。

下载在这:
LYZ_FlowManager.zip (4.07 KB, 下载次数: 97)

评分

参与人数 1星屑 +66 收起 理由
刺夜之枪 + 66 精品文章

查看全部评分

梦石
0
星屑
487
在线时间
908 小时
注册时间
2009-10-12
回帖
1702
发表于 2016-4-4 06:33:02 | 显示全部楼层
本帖最后由 日月星辰 于 2016-4-4 06:43 编辑

好的
所以我又来顶了。。。

我的流程完全是瞎糊的 最多用一个 plot 变量 以为能1~100都用上,目前大概是1,2,3,4。。。咳咳100游戏结束。
还有流程控制可以 copy 同一副地图,不同事件这样

然后这个给做大型游戏k的人比较适合,只是少有人有这种毅力 我逃 orz


顺便
才觉得lz id 瞩目。。。革命导师
回复

使用道具 举报

梦石
0
星屑
146
在线时间
22 小时
注册时间
2025-2-8
回帖
1
发表于 2025-6-4 16:50:54 | 显示全部楼层
思路太好了,很受启发
花了一两天修bug和进行优化
但楼主没再回到这个论坛还是很可惜
十年过去了,不知道近况如何
据说前端也凉了,但我这个半吊子还是很喜欢JS
回复

使用道具 举报

梦石
0
星屑
33
在线时间
3 小时
注册时间
2023-8-25
回帖
4
发表于 2025-6-17 17:53:59 | 显示全部楼层
我去,发布于2016
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部