krkr怎么手机使用 | 您所在的位置:网站首页 › kirikiroid模拟器怎么用 › krkr怎么手机使用 |
大家好,很久不见,小弟最近闭关修炼iPhone中,所以很长时间没更新博文(顺便在写某物的C++版,另外某物0.3.2版与WP7版已构建完成,不久就会发布)。这次回来,先换个与某物无关的话题,以目前用户量最大的NScripter(简称NS,以下同)与Krkr2(吉里吉里2)为代表,来简单谈谈 AVG游戏的Android环境移植吧。
______________ 关于NScripter的Android版移植: ONS和SDL: 大家都知道,日本人高桥直树是NScripter项目的发起者。然而,事实上高桥直树开发的原始版NS程式早在09年就已经停止了更新,现今已很难再看见利用原版NS开发的程式。那么,NS为何还能有现在这么庞大的用户支持率呢?答案很简单,一切都要归功于ONS的存在。应当说,目前应用最广,也是真正让NS脚本发扬光大的,还要数第三方制作的ONScripter,这一完整支持NS脚本的跨平台AVG引擎不可(简称ONS,以下同)。单独从编程角度上讲,ONS不等同于NS,由于高桥氏开发的NS程式并没有开放源码,因此ONS是通过黑盒方式参考NS效果自行模拟出的ONS功能(这个过程有点像制作游戏机模拟器),所以它并不是一个代码移植品,而应视同一个独立于NS原版的新型NS脚本解释与执行器。除了能解读同样的游戏脚本外,它与 NS就没有任何程式上的继承关系。ONS相比较NS的最大优势在于,ONS和完全依赖DirectX渲染仅支持Windows系统的NS不同,它采用了一代神人Slouken制作的SDL框架进行脚本与计算机设备交互,天生具备SDL框架“骇人听闻”的跨平台移植能力。无论是windows、linux、mac抑或PSP、PS3、PS2gs乃至wince、iphone、ipod、android平台都能看到它活跃的身影(当然,这需要相关的本地运行库配合,比如从渲染角度上讲,在Windows绘制画面既可以使用SDL提供的DirectX封装又可以使用OpenGL 封装,而到了Linux环境就只能使用OpenGL库,到了智能机或者掌机环境就要转到OpenGLES库,这些都必须有人提供相关的本地化封装,然后才能通过统一的API进行调用。即便所写代码在API层面高度一致,但在不同环境中的具体实现依旧是有差异的。也就是说,如果某个平台并没有必要的运行库支持,那么SDL也无法在该平台编译与运行。而SDL的强悍就体现在,它所提供的本地运行库相当完整,几乎涵盖了所有主流系统,兼容性却又相当优异)。凭借这种优势,目前大家所见的,绝大多数使用NS脚本开发的AVG游戏(或者狭义的指galgame),大多是以ONS而非原版NS作为运行环境——在掌机和智能机上尤其如此。可以说,没有SDL的成功,就没有今天的NS(ONS)的辉煌。这里吐个槽,前一阵小弟在某书店读到某Android教程,其中以NDK5编译了某版本的《雷神之锤》,而后就反复强调NDK移植C/C++游戏是多么方便,多么简单之类的。小弟以为,这种说法实在有些忽悠了。众所周知,网上能找到的开源版《雷神之锤》(http://www.libsdl.org/projects/quake/),使用的就是SDL这个目前世界上兼容性最强的跨平台引擎(而SDL子项目http://libsdl-android.sourceforge.net/,早已提供了SDL与Android设备的完整交互支持)。因此,即便NDK5能正常编译SDL开发的游戏,也只能证明NDK5的基本功能正常(Android好歹也是Linux核心,如果SDL在上面都跑不起来,让Google情何以堪啊),却无法理解成NDK开发有多么便捷,更不能代表所有 C/C++游戏都能轻松移植到Android环境当中(此前小弟曾和某友谈及怎么常有人能把DOS游戏移植到Android环境中运行的问题,小弟在此粗谈两点:一、世上有个开源项目叫DosBox,能够跨平台模拟标准DOS运行环境。二、DosBox是以SDL为核心开发的),就别提完全取代Java开发模式了。我们登录http://onscripter.sourceforge.jp,就可以获得关于标准版ONS的详细介绍与各版本下载路径。至于ONS-Android,则是由ONS作者提供的,完全实现了ONS功能的,专门用于跑在Android平台的ONS版本。如果您要在Android上进行NS游戏移植,首先就离不开ONS-Android的下载与编译。 ONS-Android的编译: ONS-Android的编译,仅需要如下步骤就可以做到。1 下载SDL的Android版扩展库由于标准版SDL源码包中尚未包括Android本地化支持,所以我们需要单独下载Android版SDL源码包,才能在Android环境中正常编译与运行SDL程序。事实上,所有想使用SDL以C/C++方式开发Android游戏的用户,也会需要这个SDL运行库的支持。下载地址:http://libsdl-android.sourceforge.net/(PS: ONScripter-Android内置已是这个运行库,不必真正下载,此处仅说明来源)。2 下载Android版ONScripter下载地址:http://onscripter.sourceforge.jp/android/onscripter_android.tar.gz由于ONS-Android采用JNI方式,进行C/C++部分与Java部分的交互,因此下载后的源代码也就同时包含了java(功能集中在游戏载入,界面初始化与JNI调用)与纯C(sdl-android支持库)两大部分的源码。不过,真正解释执行NS脚本的ONScripter本体(C++实现)这时却并没有包含在内(估计是作者考虑到ONScripter核心代码是所有平台共通的,才没有直接放入ONS-Android当中)。现在,我们还需要下载ONScripter的核心源码部分,才能真正进行ONS-Android编译。3 下载标准版ONScripter下载地址(也可选其它版本):http://onscripter.sourceforge.jp/onscripter-20110619.tar.gz好了,编译ONS-Android的要素全部齐备了。现在,将最后下载的ONS核心源码解压,并放入onscripter_android的jni\application文件夹下(建议解压时不要改名,因为 ONS的Android.mk配置里默认就是编译onscripter*下文件,改名很可能导致找不到目标文件(除非您重写了Android.mk配置))。这时,我们只要通过NDK编译onscripter_android项目,就能立刻得到相关的so文件了(累计将编译出九个文件,其中只有libapplication.so为ONS运行库,其余为SDL支持库),相当之简单吧? 下图为通过Cygwin在Windows中编译ONS的画面。 ONS-Android的汉化问题:出于众所周知的原因,ONS-Android默认并不支持中文编码(它是日本人做的)。这样的设计,在使用原版ONS-Android运行日文游戏时并不会有太大问题(只要该游戏没有调用第三方插件,没有使用额外API)。但是,一旦我们想要让它跑一些经过汉化的中文编码游戏呢?显而易见,肯定会造成乱码的出现。所以,如果我们想要ONS-Android能够正常地进行中文游戏显示,在进行ONS-Android编译时,便需修改其部分代码。更准确地说——是修改位于ONS核心包下的sjis2utf16.cpp文件来解决这一问题。总体来讲,ONS的字符解码过程并不复杂,sjis2utf16.cpp中仅有initSJIS2UTF16(初始化解码表到sjis_2_utf16这一数组中)、convSJIS2UTF16(转化日文编码SJIS为UTF-16编码)、convUTF16ToUTF8(转化UTF-16为UTF-8编码)这三个函数在起作用。而ONS的所有字符解码部分也会经由调用convSJIS2UTF16和convUTF16ToUTF8这两个函数产生作用(注意,initSJIS2UTF16是sjis_2_utf16变量初始化赋值时使用的函数,仅会在ONS启动时调用一次)。知道了这些,解决汉化问题就变得非常简单,只要根据现有的ONS解码规则,将其sjis_2_utf16_org数组中的SJIS日文编码表转化为我们需要的中文编码表(GBK也好,Big5也好,原理都一样,一个指定编码对应一个相对的UTF-16编码,然后以二维数组形式保存),就能够非常轻松的实现 ONS中文解码,甚至不需改写任何逻辑代码(如果有某些字符需要特殊过滤,也可以修改convSJIS2UTF16和convUTF16ToUTF8这两个函数进行拦截)。编码表较大,下文有相关下载地址。当然,如果我们想保留原版sjis2utf16.cpp内容也没问题,大可以新建一个gbk2utf16.cpp之类的文件,让两套解码器并行存在,按需求进行切换(比如想根据手机环境自适配字符解码器)。怎么做呢?粗读ONS源码我们可以发现,它实际调用到字符解码器的部分,仅集中于DirectReader.cpp和 ONScripterLabel.cpp、ONScripterLabel_text.cpp这三个源文件当中。具体的说,在于DirectReader 中的convertFromSJISToUTF8函数(其中同时调用了解码器的convSJIS2UTF16与convUTF16ToUTF8函数。 PS:该文件中还有convertFromSJISToEUC函数,是给资源文件名解码的,如果文件名中没有稀奇古怪字符的话原则上可以忽视不管,如果有的话也需要进行适当修改),以及ONScripterLabel_text.cpp中的drawGlyph函数(调用convSJIS2UTF16)和 ONScripterLabel中的initSDL函数(调用initSJIS2UTF16)。如果想自适配解码器,只需创建出相关的解码用函数(放在 gbk2utf16.cpp、big52utf16.cpp随便什么中原理都一样,改个编码表而已),继而通过最简单的if……else……判定即可(如果想根据编译环境判定,直接#if defined也行)。总之,ONS中文解码并不是什么复杂的问题,汉字编码表可以去http://unicode.org查询,或者参考Emacs项目提供的map文件(下载一个Emacs,解压后它的etc/charsets文件夹下全是后缀为.map的编码表)。还有,很久以前有人用google code发布过ONS的gbk解码版本(http://onscripter-cn.googlecode.com/svn/trunk/),有需要的朋友可以从svn下载过来参考。ONS-Android的运行机制:单从Java编程角度来说,ONS-Android的结构可谓非常简单,开放给用户的仅有Audio.java、DataDownloader.java、 GLSurfaceView_SDL.java、ONScripter.java、Video.java这五个Java文件而已(因为具体实现是 C/C++的)。其中Video.java最为重要,它包含有DemoRenderer和DemoGLSurfaceView两个子类,这不单是ONS- Android的渲染核心,而且包含了nativeInit, nativeInitJavaCallbacks, nativeDone,nativeResize,nativeMouse,nativeKey等六个jni接口。其中最主要的接口是 nativeInitJavaCallbacks以及nativeInit,只有执行了这两个jni函数,才能真正启动ONS(本质上是先启动SDL框架,附带唤醒ONS)。而执行nativeInit函数时需要注入的地址字符串,默认来源于 ONScripter类下的gCurrentDirectoryPath这个静态变量。不管我们往gCurrentDirectoryPath中放入什么字符串,默认情况下ONS都会按照这个字符串去读取/保存游戏资源(如果不能找到该路径,则ONS会立即崩掉)。至于其它,nativeDone是关闭SDL(由于ONS依赖于SDL,所以这些操作实际上都会先执行SDL部分,然后才转到ONS部分,以下同),nativeResize是改变SDL画面大小,nativeMouse触发SDL屏幕操作,nativeKey触发SDL键盘操作,皆属基础操作,并没太多好讲解的。PS:上述部分jni源码位于onscripter_android\jni\sdl\src\video\android文件夹下,如果要修改Java类名或接口名,请注意同时修改相关C代码。而 ONS-Android的启动用Activity是ONScripter类,其中真正调用ONS运行的只有runSDLApp这个私有函数,至于 runLauncher及runDownloader函数一者为要求游戏用户选择ONS资源所在路径,一者为通过网络下载ONS游戏资源,都只会在 runSDLApp执行前调用,也不会实际触发jni接口(只有runSDLApp触发jni操作)。所以,如果您不想让游戏用户使用您的APK启动其它人提供的游戏资源(也就是不想被人当模拟器用),则可以删除runLauncher函数,或者固定gCurrentDirectoryPath变量中路径字符串即可。再者,游戏初始化后默认显示于画面右侧的仅仅是Java编码的ONS操作按钮(如ESC、Skip 这些),它们仅会通过JNI方式调用相应的SDL API,而不会真正影响C/C++实现部分。因此,如果您需要改变它们的显示位置,或者进行删除、修改这些按钮的操作,乃至用其它方式彻底替代它们(比如将相关JNI调用放入Menu中,按下菜单键时才起作用),都只需修改相关Java代码即可,无需改变任何C/C++部分。另外,通过解读源码我们可以获悉,在ONS-Android初始化运行时,有三种文件必不可少。一是脚本文件,它可以命名为0.txt、00.txt、nscr_sec.dat、nscript.___、nscript.dat这五种名称中的任意一种(后三种都属于NS的dat文件包,需要通过工具打包,网络有下载),但除此之外的名称一概不认,没有则无法运行游戏。二是游戏资源文件,也就是NS中使用的arc.nsa,游戏中使用的音频与图像文件强制要求打成此包(NS提供有打包工具),并且保持此名称不变,否则ONS还是不认。三是default.ttf,也就是字库文件,由于ONS-Android默认情况下不能使用Android字库,所以此文件必须存在,并且正常可读(必须能够被SDL识别),否则游戏会强制退出(没错,如果字库不存在或者读取异常,ONS直接就崩了~连错误都不报~)。有了上述三种文件,ONS才能在 Android中正常运行。最后,虽然AVG游戏通常需要较大的音频与图像文件支持,Android版ONS默认要求将游戏资源文件保存于SD卡中。但经实测发现,如果将gCurrentDirectoryPath设定为其它可读写目录,只要上述三文件正常无误,ONS-Android一样能正常运行(比如APK的Cache文件夹)。所以,如果我们想对游戏资源作一些手脚(在内存而非SD卡中进行游戏什么的),完全可以根据此特性入手。 ONS-Android的运行效果:真机运行效果:
***************** package net.studiomikan.kas;import java.util.HashMap;import java.util.TreeMap;// 标签对象集合(KAS的脚本解析方式是将所有同指令的命令都放在一个集合中,所以有此接口)interface TagObject{ public void run(HashMap elm);}// 标签集合处理器public class TagHandlers{ private TreeMap tagHandlersMap = null; private MainSurfaceView owner; public TagHandlers(MainSurfaceView owner) { tagHandlersMap = new TreeMap(); getTagHandlers(owner); } // 返回指定标签名下属的所有脚本集合 public TagObject getTagObject(String tagName) { return tagHandlersMap.get(tagName); } // 当传递的MainSurfaceView不为null时,则根据MainSurfaceView中的脚本数据构建出完整的标签树 public void getTagHandlers(MainSurfaceView owner) { if(owner == null) return; this.owner = owner; getTagHandlers(); } //PS:KAS并没有完整的实现KAG脚本,下面给出的脚本指令不足标准KAG的1/3 public void getTagHandlers() { // s // 停止执行脚本 tagHandlersMap.put("s", new TagObject(){ public void run(HashMap elm){ owner.tag_s(); }}); // wait // 暂停 tagHandlersMap.put("wait", new TagObject(){ public void run(HashMap elm){ owner.tag_wait(elm); }}); // r // 换行 tagHandlersMap.put("r", new TagObject(){ public void run(HashMap elm){ owner.tag_r(); }}); // er // 消去消息层的文字 tagHandlersMap.put("er", new TagObject(){ public void run(HashMap elm){ owner.tag_er(); }}); // ct // 重构消息层MessageLayer tagHandlersMap.put("ct", new TagObject(){ public void run(HashMap elm){ owner.tag_ct(); }}); // cm // 清空全部消息层中的文字 tagHandlersMap.put("cm", new TagObject(){ public void run(HashMap elm){ owner.tag_cm(); }}); // p // 显示完一页的消息后必须点击屏幕才允许换页 tagHandlersMap.put("p", new TagObject(){ public void run(HashMap elm){ owner.tag_p(); }}); // l // 文字显示到行末时必须点击屏幕才允许换行 tagHandlersMap.put("l", new TagObject(){ public void run(HashMap elm){ owner.tag_l(); }}); // nowait // 瞬间显示出全部文字 tagHandlersMap.put("nowait", new TagObject(){ public void run(HashMap elm){ owner.tag_nowait(); }}); // endnowait // 结束瞬间显示全部文字模式 tagHandlersMap.put("endnowait", new TagObject(){ public void run(HashMap elm){ owner.tag_endnowait(); }}); // position // 消息层的属性设置 /* 参数: (1)对象层位置:layer = message/message0/message1 (2)页面类型:page = fore/back (3)层是否可见:visible = true/false (4)层的颜色:color = 整型色彩值 (5)不透明度:opacity = 0(完全透明)~255(完全不透明) (6)层左端位置:left = 0 以上整数 (7)层上端位置:top = 0 以上整数 (8)宽:width = 0 以上整数 (9)高:height = 0 以上整数 (10)Layer图像:frame = "Layer名" (11)Layer图像的透明色:framekey = adapt/整型色彩值 (12)左方边距:marginl = 0 以上整数 (13)上方边距:margint = 0 以上整数 (14)右方边距:marginr = 0 以上整数 (15)下方边距:marginb = 0 以上整数 (16)纵向书写模式:vertical = false(默认)/true (17)是否允许用鼠标拖动:draggable = false(默认)/true */ tagHandlersMap.put("position", new TagObject(){ public void run(HashMap elm){ owner.tag_position(elm); }}); // layopt // 标准层的属性设定 /* 参数: (1)对象层位置:layer = message/message0/message1/0/1/2…… (2)页面类型:page = fore/back (3)层是否可见:visible = true/false (4)层左端位置:left = 0以上整数 (5)层上端位置:top = 0以上整数 (6)不透明度:opacity = 0(完全透明)~255(完全不透明) (7)消息层是否需要隐藏:autohide = true/false (8)重叠顺序:index = 0以上整数 */ tagHandlersMap.put("layopt", new TagObject(){ public void run(HashMap elm){ owner.tag_layopt(elm); }}); // image // 读取图像 tagHandlersMap.put("image", new TagObject(){ public void run(HashMap elm){ owner.tag_image(elm); }}); // jump // 跳转到指定脚本脚本 /* 参数: (1)要跳转到的脚本文件:storage="文件名.ks" (2)要跳转到的标签名:target="*标签名" (3)是否将这个跳转之后的部分看作“已读”:countpage=false(默认)/true */ tagHandlersMap.put("jump", new TagObject(){ public void run(HashMap elm){ owner.tag_jump(elm); }}); // call // 跳转到指定脚本文件里并执行相应标签 /* 参数: (1)要跳转到的脚本文件:storage="文件名.ks" (2)要跳转到的标签名:target="*标签名" (3)是否将这个跳转之后的部分看作“已读”:countpage=false(默认)/true */ tagHandlersMap.put("call", new TagObject(){ public void run(HashMap elm){ owner.tag_call(elm); }}); // return // 返回指定的脚本位置 /* 参数: (1)要跳转到的脚本文件:storage="文件名.ks" (2)要跳转到的标签名:target="*标签名" (3)是否将这个跳转之后的部分看作“已读”:countpage=false(默认)/true */ tagHandlersMap.put("return", new TagObject(){ public void run(HashMap elm){ owner.tag_return(); }}); // current // 指定当前操作的消息层 /* 参数: (1)层名:layer = message/message0/message1 (2)页面:page = fore(默认)/back (3)是否需要同时写入背景页面(BackPage)中:withback = false/true */ tagHandlersMap.put("current", new TagObject(){ public void run(HashMap elm){ owner.tag_current(elm); }}); // trans // 命令游戏层进行渐变转换(这个渐变效果是根据分解渐变图像素而生成的,所以在Android模拟器中很慢……) /* 参数: (1)渐变转换的时间:time = 0 以上整数(毫秒) (2)渐变转换的类型:method = universal(自定义,默认)/ crossfade(淡入淡出) (3)对象层:layer = message/message0/message1/base/0/1/2 (4)是否包含子层:children = true(默认)/false (5)转换规则图像(仅当method = universal时有效):rule = "图像文件名" (6)模糊程度值(仅当method = universal时有效):vague = 0 以上整数 (7)卷动方向(仅当method = scroll时有效):from = left/top/right/bottom */ tagHandlersMap.put("trans", new TagObject(){ public void run(HashMap elm){ owner.tag_trans(elm); }}); // backlay // 将层的前景页面信息复制到背景页面中 tagHandlersMap.put("backlay", new TagObject(){ public void run(HashMap elm){ owner.tag_backlay(elm); }}); // playbgm // 播放背景音乐 /* 参数: (1)音效文件:storage="音效文件名" (2)是否循环播放:loop=false(默认)/true (3)音效缓冲编号:0(默认)/1/2 */ tagHandlersMap.put("playbgm", new TagObject(){ public void run(HashMap elm){ owner.tag_playbgm(elm); }}); // bgmopt // 设定背景音乐的属性 /* 参数: (1)音量的百分数:volume = 0~100 (2)最大音量百分数:gvolume = 0~100 */ tagHandlersMap.put("bgmopt", new TagObject(){ public void run(HashMap elm){ owner.tag_bgmopt(elm); }}); // stopbgm // 停止播放背景音乐 tagHandlersMap.put("stopbgm", new TagObject(){ public void run(HashMap elm){ owner.tag_stopbgm(elm); }}); // playse // 播放音效 /* 参数: (1)音效文件:storage = "音效文件名" (2)是否循环播放:loop = false(默认)/true (3)音效缓冲编号:0(默认)/1/2 */ tagHandlersMap.put("playse", new TagObject(){ public void run(HashMap elm){ owner.tag_playse(elm); }}); // seopt // 音效设定 /* 参数: (1)音效缓冲编号:buf = 0(默认)/1/2 (2)音量:volume = 0~100(%) */ tagHandlersMap.put("seopt", new TagObject(){ public void run(HashMap elm){ owner.tag_seopt(elm); }}); // stopse // 停止播放音效 /* 参数: (1)音效缓冲编号:buf = 0(默认)/1/2 */ tagHandlersMap.put("stopse", new TagObject(){ public void run(HashMap elm){ owner.tag_stopse(elm); }}); // quake // 画面震动 /* 参数: (1)震动的时间:time = 0 以上整数(毫秒) (2)time属性的单位:timemode = ms/delay (3)横向的最大振幅:hmax = 0以上整数 (4)纵向的最大振幅:vmax = 0以上整数 */ tagHandlersMap.put("quake", new TagObject(){ public void run(HashMap elm){ owner.tag_quake(elm); }}); // stopquake // 停止画面震动 tagHandlersMap.put("stopquake", new TagObject(){ public void run(HashMap elm){ owner.tag_stopquake(); }}); // wq // 等待画面震动停止 tagHandlersMap.put("wq", new TagObject(){ public void run(HashMap elm){ owner.tag_wq(elm); }}); // hidemessage // 隐藏消息层 tagHandlersMap.put("hidemessage", new TagObject(){ public void run(HashMap elm){ owner.tag_hidemessage(); }}); // gotostart // 回到startanchor标签指定的地点 /* 参数: (1)是否需要确认:ask=false(默认)/true */ tagHandlersMap.put("gotostart", new TagObject(){ public void run(HashMap elm){ owner.tag_gotostart(elm); }}); // link // 外部链接 /* 参数: (1)要跳转到的脚本文件:storage = "文件名.ks" (2)要跳转到的标签名:target = "*标签名" (3)链接色:color = 颜色值 (4)鼠标进入时的音效:enterse = "音效文件名" (5)鼠标进入时的音效的缓冲编号:entersebuf = 0/1/2 (6)鼠标点击时的音效:clickse = "音效文件名" (7)鼠标点击时的音效的缓冲编号:clicksebuf = 0/1/2 (8)鼠标退出时的音效:leavese = "音效文件名" (9)鼠标退出时的音效的缓冲编号:leavesebuf = 0/1/2 (10)是否将这个跳转之后的部分看作“已读”:countpage = true(默认)/false */ tagHandlersMap.put("link", new TagObject(){ public void run(HashMap elm){ owner.tag_link(elm); }}); // endlink // 结束链接 tagHandlersMap.put("endlink", new TagObject(){ public void run(HashMap elm){ owner.tag_endlink(); }}); // locklink // 锁定链接 tagHandlersMap.put("locklink", new TagObject(){ public void run(HashMap elm){ owner.tag_locklink(); }}); // unlocklink // 解锁链接 tagHandlersMap.put("unlocklink", new TagObject(){ public void run(HashMap elm){ owner.tag_unlocklink(); }}); // deffont // 设定默认的文字属性 /* 参数: (1)字体名:face = "字体名" (2)文字大小:size = 0以上整数 (3)文字颜色:color = 颜色值 (4)是否粗体:bold = false(默认)/true (5)是否描边:edge = false(默认)/true (6)描边颜色:edgecolor = 颜色值 (7)是否显示阴影:shadow = true(默认)/false (8)阴影颜色:shadowcolor = 颜色值 */ tagHandlersMap.put("deffont", new TagObject(){ public void run(HashMap elm){ owner.tag_deffont(elm); }}); // defstyle // 设定默认的文字风格 /* 参数: (1)字间距:pitch = 0 以上整数 (2)行间距:linespacing = 0 以上整数 (3)列间距:linesize = 0 以上整数 */ tagHandlersMap.put("defstyle", new TagObject(){ public void run(HashMap elm){ owner.tag_defstyle(elm); }}); // laycount // 更改层的数量 /* 参数: (1)普通层的数量:layers = 0 以上整数 (2)消息层的数量:messages = 1 以上整数 */ tagHandlersMap.put("laycount", new TagObject(){ public void run(HashMap elm){ owner.tag_laycount(elm); }}); // fadeoutbgm // 淡出背景音乐 tagHandlersMap.put("fadeoutbgm", new TagObject(){ public void run(HashMap elm){ owner.tag_fadeoutbgm(elm); }}); // fadeoutse // 淡出音效 tagHandlersMap.put("fadeoutse", new TagObject(){ public void run(HashMap elm){ owner.tag_fadeoutse(elm); }}); // fadeinbgm // 淡入背景音乐 tagHandlersMap.put("fadeinbgm", new TagObject(){ public void run(HashMap elm){ owner.tag_fadeinbgm(elm); }}); // fadeinse // 淡入音效 tagHandlersMap.put("fadeinse", new TagObject(){ public void run(HashMap elm){ owner.tag_fadeinse(elm); }}); // move // 移动层 /* 参数: (1)对象层:layer = message/message0/message1/0/1/2…… (2)移动的位置:path = "(x1,y1,opacity1)(x2,y2,opacity2)……" (3)到达一个点 (x,y,opacity) 所用的时间:time = 0以上整数(毫秒) (4)页面:page = fore/back (5)加速度:accel = 0(默认)/正数/负数 (6)动作开始前的延迟时间:delay = 0以上整数(毫秒) */ tagHandlersMap.put("move", new TagObject(){ public void run(HashMap elm){ owner.tag_move(elm); }}); // load // 载入存档 /* 参数: (1)保存的位置编号:place = 0 以上整数(0为默认) (2)是否需要确认:ask = false(默认)/true */ tagHandlersMap.put("load", new TagObject(){ public void run(HashMap elm){ owner.tag_load(elm); }}); // save // 保存存档 /* 参数: (1)保存的位置编号:place = 0 以上整数(0为默认) (2)是否需要确认:ask = false(默认)/true */ tagHandlersMap.put("save", new TagObject(){ public void run(HashMap elm){ owner.tag_save(elm); }}); //------------------------------------------------------------------------------------------ // 系统操作指令 // autowc // 自动等待 /* 参数: (1)自动等待输入的文字:ch = "文字对象" (2)自动等待是否有效:enabled = true/false (3)等待时间:time = 0 以上整数 */ tagHandlersMap.put("autowc", new TagObject(){ public void run(HashMap elm){ owner.tag_autowc(elm); }}); // clearsysvar // 消除所有系统变量 tagHandlersMap.put("clearsysvar", new TagObject(){ public void run(HashMap elm){ owner.tag_clearsysvar(); }}); // clickskip // 在点击画面时允许跳过当前脚本进度 tagHandlersMap.put("clickskip", new TagObject(){ public void run(HashMap elm){ owner.tag_clickskip(elm); }}); // close // 脚本结束 tagHandlersMap.put("close", new TagObject(){ public void run(HashMap elm){ owner.tag_close(elm); }}); // title // 指定标题 tagHandlersMap.put("title", new TagObject(){ public void run(HashMap elm){ owner.tag_title(elm); }}); // waitclick // 在点击画面后才能继续进行脚本解析 tagHandlersMap.put("waitclick", new TagObject(){ public void run(HashMap elm){ owner.tag_waitclick(); }}); // wc // 设定文字显示间隔时间 tagHandlersMap.put("wc", new TagObject(){ public void run(HashMap elm){ owner.tag_wc(elm); }}); //------------------------------------------------------------------------------------------ // 宏指令 // erasemacro // 清除宏 tagHandlersMap.put("erasemacro", new TagObject(){ public void run(HashMap elm){ owner.tag_erasemacro(elm); }}); //------------------------------------------------------------------------------------------ // 自动阅读模式 // cancelautomode // 解除“自动阅读”模式 tagHandlersMap.put("cancelautomode", new TagObject(){ public void run(HashMap elm){ owner.tag_cancelautomode(); }}); // cancelskip // 解除跳过模式 tagHandlersMap.put("cancelskip", new TagObject(){ public void run(HashMap elm){ owner.tag_cancelskip(); }}); // ch // 显示文字 tagHandlersMap.put("ch", new TagObject(){ public void run(HashMap elm){ owner.tag_ch(elm); }}); // indent // 设定文字缩进 tagHandlersMap.put("indent", new TagObject(){ public void run(HashMap elm){ owner.tag_indent(); }}); // endindent // 解除文字缩进 tagHandlersMap.put("endindent", new TagObject(){ public void run(HashMap elm){ owner.tag_endindent(); }}); // locate // 指定文字的显示位置 /* 参数: (1)横方向位置:x = 0 以上整数 (2)纵方向位置:y = 0 以上整数 */ tagHandlersMap.put("locate", new TagObject(){ public void run(HashMap elm){ owner.tag_locate(elm); }}); // delay // 文字显示速度 tagHandlersMap.put("delay", new TagObject(){ public void run(HashMap elm){ owner.tag_delay(elm); }}); //------------------------------------------------------------------------------------------ // 历史数据 // clearhistory : KAS专有,非标准KAG脚本语句 // 清空历史数据 tagHandlersMap.put("clearhistory", new TagObject(){ public void run(HashMap elm){ owner.tag_clearhistory(); }}); // history // 历史设定 /* 参数: (1)历史是否可显示:enabled=true/false (2)是否输出文字信息至历史:output=true/false */ tagHandlersMap.put("history", new TagObject(){ public void run(HashMap elm){ owner.tag_history(elm); }}); // hr // 历史的换行/换页 /* 参数: (1)换行是否需要换页:repage=false(默认)/true */ tagHandlersMap.put("hr", new TagObject(){ public void run(HashMap elm){ owner.tag_hr(elm); }}); // showhistory // 显示历史数据 tagHandlersMap.put("showhistory", new TagObject(){ public void run(HashMap elm){ owner.tag_showhistory(); }}); //------------------------------------------------------------------------------------------ // 跳转指令 // button // 图形按钮(PS:几乎没有实现标准KAG脚本button标签应有的功能……) tagHandlersMap.put("button", new TagObject(){ public void run(HashMap elm){ owner.tag_button(elm); }}); //------------------------------------------------------------------------------------------ // 层指令 // copylay // 复制层 /* 参数: (1)复制源层:srclayer = message/message0/message1/base/0/1/2…… (2)复制目标层:destlayer = message/message0/message1/base/0/1/2…… (3)复制源页面:srcpage = fore/back (4)复制目标页面:destpage = fore/back */ tagHandlersMap.put("copylay", new TagObject(){ public void run(HashMap elm){ owner.tag_copylay(elm); }}); // freeimage // 释放图像层资源 tagHandlersMap.put("freeimage", new TagObject(){ public void run(HashMap elm){ owner.tag_freeimage(elm); }}); // stopmove // 停止层的移动 tagHandlersMap.put("stopmove", new TagObject(){ public void run(HashMap elm){ owner.tag_stopmove(); }}); // stoptrans // 停止层的渐变转换 tagHandlersMap.put("stoptrans", new TagObject(){ public void run(HashMap elm){ owner.tag_stoptrans(); }}); // wm // 等待层自动移动结束 tagHandlersMap.put("wm", new TagObject(){ public void run(HashMap elm){ owner.tag_wm(elm); }}); //------------------------------------------------------------------------------------------ // 音效指令 // fadebgm // 淡入背景音乐 tagHandlersMap.put("fadebgm", new TagObject(){ public void run(HashMap elm){ owner.tag_fadebgm(elm); }}); // fadese // 淡入音效音乐 tagHandlersMap.put("fadese", new TagObject(){ public void run(HashMap elm){ owner.tag_fadese(elm); }}); // pausebgm // 暂停背景音乐 tagHandlersMap.put("pausebgm", new TagObject(){ public void run(HashMap elm){ owner.tag_pausebgm(); }}); // resumebgm // 继续播放背景音乐 tagHandlersMap.put("resumebgm", new TagObject(){ public void run(HashMap elm){ owner.tag_resumebgm(); }}); // wb // 等待背景音乐淡出 tagHandlersMap.put("wb", new TagObject(){ public void run(HashMap elm){ owner.tag_wb(elm); }}); // wf // 等待音效淡出 tagHandlersMap.put("wf", new TagObject(){ public void run(HashMap elm){ owner.tag_wf(elm); }}); // wl // 等待背景音乐播放结束 tagHandlersMap.put("wl", new TagObject(){ public void run(HashMap elm){ owner.tag_wl(elm); }}); // ws // 等待音效播放结束 tagHandlersMap.put("ws", new TagObject(){ public void run(HashMap elm){ owner.tag_ws(elm); }}); //------------------------------------------------------------------------------------------ // 变量指令(PS:由于没有TJS解释器,所以TJS相关部分不具备) // clearvar // 清理所有游戏变量 tagHandlersMap.put("clearvar", new TagObject(){ public void run(HashMap elm){ owner.tag_clearvar(); }}); // emb // 显示TJS脚本的执行结果(在KAS中仅仅支持四则运算罢了) tagHandlersMap.put("emb", new TagObject(){ public void run(HashMap elm){ owner.tag_emb(elm); }}); //------------------------------------------------------------------------------------------ // 存档指令 // copybookmark // 复制存档 tagHandlersMap.put("copybookmark", new TagObject(){ public void run(HashMap elm){ owner.tag_copybookmark(elm); }}); // disablestore // 禁止存档 tagHandlersMap.put("disablestore", new TagObject(){ public void run(HashMap elm){ owner.tag_disablestore(elm); }}); // erasebookmark // 删除存档 tagHandlersMap.put("erasebookmark", new TagObject(){ public void run(HashMap elm){ owner.tag_erasebookmark(elm); }}); // startanchor // 即时存档,同时也是gotostart指令的返回点 tagHandlersMap.put("startanchor", new TagObject(){ public void run(HashMap elm){ owner.tag_startanchor(elm); }}); // store // 开启存档功能 tagHandlersMap.put("store", new TagObject(){ public void run(HashMap elm){ owner.tag_store(elm); }}); // tempload // 读取内存上的临时存档 tagHandlersMap.put("tempload", new TagObject(){ public void run(HashMap elm){ owner.tag_tempload(elm); }}); // tempsave // 保存临时存档到游戏内存 tagHandlersMap.put("tempsave", new TagObject(){ public void run(HashMap elm){ owner.tag_tempsave(elm); }}); //------------------------------------------------------------------------------------------ // 变量指令 // assign : KAS专有指令,非标准KAG脚本 // 将指定数值插入游戏变量中 tagHandlersMap.put("assign", new TagObject(){ public void run(HashMap elm){ owner.tag_assign(elm); }}); // fillcolorbase : KAS专有指令,非标准KAG脚本 // 填充北京为指定颜色 tagHandlersMap.put("fillcolorbase", new TagObject(){ public void run(HashMap elm){ owner.tag_fillcolorbase(elm); }}); // setversion : KAS专有指令,非标准KAG脚本 // 设定游戏版本 tagHandlersMap.put("setversion", new TagObject(){ public void run(HashMap elm){ owner.tag_setversion(elm); }}); // callload : KAS专有指令,非标准KAG脚本 // 呼出游戏读档界面 tagHandlersMap.put("callload", new TagObject(){ public void run(HashMap elm){ owner.tag_callload(); }}); // callsave : KAS专有指令,非标准KAG脚本 // 呼出游戏存档界面 tagHandlersMap.put("callsave", new TagObject(){ public void run(HashMap elm){ owner.tag_callsave(); }}); // printlayerstate : 打印出游戏状态(后台执行) tagHandlersMap.put("printlayerstate", new TagObject(){ public void run(HashMap elm){ owner.tag_debug_printlayerstate(elm); }}); }}***************** 此外,KAS默认的屏幕大小为800x450。作者给出的效果图:
|
CopyRight 2018-2019 实验室设备网 版权所有 |