Project1

标题: 【大佬请进】我利用Game_Event.prototype.event = function() {做了shi... [打印本页]

作者: 任小雪    时间: 2023-6-29 04:15
标题: 【大佬请进】我利用Game_Event.prototype.event = function() {做了shi...
本帖最后由 任小雪 于 2023-6-29 12:42 编辑

我利用Game_Event.prototype.event = function() {实现了事件拷贝(也许是实现了)。
但是,遇到了一个问题,那就是,存档后关游戏再读档后,只要进入该地图,游戏就会变卡(不确定是不是与这些有关:地图大小是27*23,地图里的事件数目也是这个)。
大佬们有什么好的建议或者猜测也行,我自己摸索一般是真的“俺寻思”全靠莽,唔。

JAVASCRIPT 代码复制
  1. var Map_Area=function(){//【bug:蓝色水晶传送回城时,支线人的图像不显示,貌似其实跟传送事件本身的图像刷新没做好有关,跟本插件无关】
  2. //地图面积控制//【bug,做到这,弄到这:直达传送野外大图到野外小图,坐标因不存在致使人物无法移动,而且第二个问题是容易跳bug(小地图插件功能方面);直达传送野外小图到野外大图,事件数目不对(往返庄园各一次倒是会恢复正常)——取巧的法子也许是将直达传送修改为仅能传送到休息层等非野外地图】
  3.  
  4. //根据地图id以及周目等条件(最好不能是层数或者小层数这种没有缓存的即时变量,否则会出bug),修改地图大小,以影响事件数量(跟事件拷贝有关)
  5. if(2==2){var Width=17+LCH.dangqianzhoumu.toString().length%10;var Height=13+LCH.dangqianzhoumu.toString().length%10;};//【地图一旦长超过27,宽超过23,下面事件的位置就会出错,即使归位也会出错,也许是因为东西太多,太卡,一时间执行不来导致的】【存档前的地图面积不能比存档后的大,否则无法读档,貌似因部分事件已经不存在,但读档时,程序还得遍寻它们】
  6.  
  7. ////根据地图决定传送阵位置(只能放这里,亦或者,需要单独弄一个function,然后内含return,需要就调用一下(指用到传送阵位置或id的地方,需要才调用貌似更省算力))
  8. var ID1=43;var ID2=179;var ID3=213;
  9. if(Width%2==1){var ID1=Width*2+Width/2+0.5;}else if(Width%2==0){var ID1=Width*2+Width/2;};
  10. if(Width%2==1){var ID2=Width*Height-(Width*2+Width/2-0.5);}else if(Width%2==0){var ID2=Width*Height-(Width*2+Width/2-1);};
  11. if(Width%2==1){var ID3=Width*Height-(Width/2-0.5);}else if(Width%2==0){var ID3=Width*Height-(Width/2);};
  12. var j=[ID1,ID2,ID3];for(var i=1;i<=j.length;i++){LCH.Map_Csz_XY[i*3-3]=j[i-1];LCH.Map_Csz_XY[i*3-2]=(j[i-1]-1)%Width;LCH.Map_Csz_XY[i*3-1]=Math.floor((j[i-1]-1)/Width);};
  13. ////
  14.  
  15. if(($gameMap.mapId()==6||$gameMap.mapId()==7)){$dataMap.width=Width;$dataMap.height=Height;};
  16.  
  17. Map_EventSetup();//事件生成(为了复制某些事件)
  18.  
  19. };
  20.  
  21. Game_Map.prototype.width = function() {
  22. Map_Area();//地图面积控制
  23.     return $dataMap.width;
  24. };
  25.  
  26. Game_Map.prototype.height = function() {
  27. Map_Area();//地图面积控制
  28.     return $dataMap.height;
  29. };
  30.  
  31. Game_Event.prototype.event = function() {
  32. Map_Area();//地图面积控制
  33.     return $dataMap.events[this._eventId];
  34. };
  35.  
  36. var Map_EventSetup=function(){//事件生成(为了复制某些事件)
  37. if(($gameMap.mapId()==6||$gameMap.mapId()==7)){LCH.Map_Event_Long=$dataMap.events.length;};//最省$dataMap.events.length算力的法子只有这个,其他一次性的貌似都会跳bug,再研究下去大概只能看看存档读档的插件什么情况碰碰运气
  38. /*
  39. if($gameMap._mapId==1&&LCH.Map_Event_Long<26+LCH.dangqianzhoumu){//用本部分间接实现事件拷贝,这里是控制第一张地图拷贝“事件5”两次,注意,前提是这张图本身的事件只有26个(包括空白事件)
  40. var i=JsonEx.makeDeepCopy($dataMap.events[5]);i.id=LCH.Map_Event_Long;
  41. $dataMap.events.push(i);
  42. };
  43. */
  44. //
  45. if($gameMap._mapId==6||$gameMap._mapId==7){//【bug,做到这,弄到这】存档读档后变卡了,除非地图原本那样的不大,可能只是地图太大本身就会卡。。。由此,除非是那种需要小地图内不断产生小兵和消灭小兵的地图,否则,貌似无限生成新事件也意义不大
  46.  
  47. //也许是以下的条件$dataMap.events需要读取,太大才卡,也许可以尝试弄一个相应的开关,在传送整个结束后开启这个开关,然后下面整个结束后(事件相等且位置归位完成)关闭这个开关,而以这个开关作为条件以判定以下整个东西是否执行,这个条件也许可以加在这里的if($gameMap._mapId==6||$gameMap._mapId==7){括号里
  48.  
  49. if(LCH.Map_Event_Long-1<$dataMap.width*$dataMap.height){//本条件可以实现野外触碰事件和格子数相同
  50. for(var j=1;j<=$dataMap.width*$dataMap.height-(LCH.Map_Event_Long-1);j++){
  51. var i=JsonEx.makeDeepCopy($dataMap.events[1]);i.id=LCH.Map_Event_Long;
  52. $dataMap.events.push(i);
  53. };
  54. LCH.Map_Freshed=0;
  55.  
  56. /*//当前这一段暂时没有意义,不能“解决存档前的地图面积不能比存档后的大”的问题
  57. }else if(LCH.Map_Event_Long-1>$dataMap.width*$dataMap.height){
  58. $dataMap.events=$dataMap.events.slice(0,$dataMap.width*$dataMap.height+2);//"Hello world!".slice(1,5)=="ello"
  59. LCH.Map_Freshed=0;
  60. *///
  61.  
  62. }else if(LCH.Map_Event_Long-1==$dataMap.width*$dataMap.height&&LCH.Map_Freshed==0){//各个格子事件生成结束后,非默认地图大小时,重新设置传送阵位置&&$dataMap.width!==17||$dataMap.height!==13
  63. ////
  64. if($gameMap._mapId==6){//&&($dataMap.events[43].meta.leixing=="csz"&&$dataMap.events[179].meta.leixing=="csz")
  65. var i1=JsonEx.makeDeepCopy($dataMap.events[43]);i1.id=LCH.Map_Csz_XY[0];
  66. var i2=JsonEx.makeDeepCopy($dataMap.events[179]);i2.id=LCH.Map_Csz_XY[3];
  67. var i=JsonEx.makeDeepCopy($dataMap.events[1]);i.id=43;$dataMap.events[i.id]=i;
  68. var i=JsonEx.makeDeepCopy($dataMap.events[1]);i.id=179;$dataMap.events[i.id]=i;
  69. $dataMap.events[i1.id]=i1;
  70. $dataMap.events[i2.id]=i2;
  71. ////
  72. if($dataMap.events[i1.id].x!==(i1.id-1)%$dataMap.width||$dataMap.events[i1.id].y!==Math.floor((i1.id-1)/$dataMap.width)||
  73. $dataMap.events[i2.id].x!==(i2.id-1)%$dataMap.width||$dataMap.events[i2.id].y!==Math.floor((i2.id-1)/$dataMap.width)){
  74. var l1=$dataMap.width*$dataMap.height;for(var i=1;i<=l1;i++){
  75. $dataMap.events[i].x=(i-1)%$dataMap.width;$dataMap.events[i].y=Math.floor((i-1)/$dataMap.width);
  76. };
  77. };//传送事件归位//【bug:部分事件会重叠,也许要先都变成不动的事件,再归位,再变回正确的事件才行。。。不排除是因为事件太多地图太大太卡而已】
  78. /////
  79. }else if($gameMap._mapId==7){//&&$dataMap.events[213].meta.leixing=="csz"
  80. var i1=JsonEx.makeDeepCopy($dataMap.events[213]);i1.id=LCH.Map_Csz_XY[6];
  81. var i=JsonEx.makeDeepCopy($dataMap.events[1]);i.id=213;$dataMap.events[i.id]=i;
  82. $dataMap.events[i1.id]=i1;
  83. ////
  84. if($dataMap.events[i1.id].x!==(i1.id-1)%$dataMap.width||$dataMap.events[i1.id].y!==Math.floor((i1.id-1)/$dataMap.width)){
  85. var l1=$dataMap.width*$dataMap.height;for(var i=1;i<=l1;i++){
  86. $dataMap.events[i].x=(i-1)%$dataMap.width;$dataMap.events[i].y=Math.floor((i-1)/$dataMap.width);
  87. };
  88. };//传送事件归位
  89. /////
  90. };
  91. ////
  92. LCH.Map_Freshed=1;
  93. };
  94. };
  95. //
  96. };

作者: 小秋橙    时间: 2023-6-29 04:16
// 启动时加载所有地图到$dataMapInfos,以后切换地图时直接取用结果
let loadDatabase = DataManager.loadDatabase;
DataManager.loadDatabase = function () {
// 可以使用下一行这样的语法追加自己的json文件
// this._databaseFiles.unshift({ name: '$dataXxx', src: 'Xxx.json' });
this._databaseFiles.pop(); // 移除MapInfos.json,因为要另外fetch
loadDatabase.apply(DataManager, arguments);
fetch('data/MapInfos.json').then(s => s.json()).then(a => {
window.$dataMapInfos = new Array(a.length);
for (let i = a.length; --i >= 0; a[i] ?? ($dataMapInfos[i] = null));
for (const o of a)
o && fetch('data/Map' + o.id.padZero(3) + '.json').then(s => s.json()).then(
map => this.onLoad($dataMapInfos[o.id] = Object.assign(map, o))
);
});
}
let isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function () {
return window.$dataMapInfos?.includes(/*undefined*/) === false &&
isDatabaseLoaded.apply(DataManager, arguments);
}
DataManager.loadMapData = function (mapId) {
mapId > 0 ? $dataMap = $dataMapInfos[mapId] : this.makeEmptyMap();
}
按照楼上的说法,游戏启动时应该一次性加载好所有地图文件,就像上面这样。
然后我不太清楚楼主的【克隆事件】是在什么时候做的,如果是在游戏启动时做,我的办法是像下面这样用区域ID:
// 地图事件的spawn机制:根据各点的区域编码从样板地图量产事件
let onDatabaseLoaded = Scene_Boot.prototype.onDatabaseLoaded;
Scene_Boot.prototype.onDatabaseLoaded = function () {
onDatabaseLoaded.apply(this, arguments);
for (const map of $dataMapInfos) {
if (map == null || $dataMapInfos[map.meta.template] == null) continue;
let src = $dataMapInfos[map.meta.template].events,
i = map.events.length, w = map.width, h = map.height;
for (let y = 0; y < h; ++y) for (let x = 0; x < w; ++x) {
let id = map.data[(5 * h + y) * w + x]; // 六等分的最后一段
if (id > 0 && src[id] != null) {
map.events[i] = Object.assign(
JSON.parse(JSON.stringify(src[id])), { 'id': i, 'x': x, 'y': y }
);
++i;
}
}
}
}
作者: 闪电超重火炮    时间: 2023-6-29 08:00
看看实现过程,确定是不是跟多个事件有关,另外是否存在持续进行的并行事件在持续调用event()
作者: 闪电超重火炮    时间: 2023-6-29 08:08
另外,你说你是在执行完事件之后存档,那么你去检查下对应的$dataMap的数据中的events一项,该项是否过于复杂或者嵌套,在当前地图检索当前地图的events()
$gameMap.events()以及在是否有异常,地图会每帧执行事件刷新指令,以检索是否有事件达到条件执行
作者: resty    时间: 2023-6-29 14:17
不会mv,不一定和你遇到的问题有关,随便看了下
JAVASCRIPT 代码复制
  1. for (var j = 1; j <= $dataMap.width * $dataMap.height - (LCH.Map_Event_Long - 1); j++) {
  2.                 var i = JsonEx.makeDeepCopy($dataMap.events[1]);
  3.                 i.id = LCH.Map_Event_Long;
  4.                 $dataMap.events.push(i);
  5. };

这一段里生成的id全都等于LCH.Map_Event_Long,也许你会想要的是 i.id = LCH.Map_Event_Long + j - 1

作者: 百里_飞柳    时间: 2023-6-29 22:09
本帖最后由 百里_飞柳 于 2023-6-29 22:16 编辑

你这个事件拷贝简直是打数据库的脸,疯狂给dataMap这个本应该由编辑器修改的变量增加新的数据……

我在va里写事件拷贝时,是这样的思路:
1. 新增一个全局变量,里面存了各个地图的拷贝事件信息的数据(地图ID => [ [原事件的所在地图,原事件的ID,拷贝后的地图x,拷贝后的地图y, 拷贝后的事件ID] ])
2. 在地图切换时(以及读档后),从全局变量里读取该地图对应的全部拷贝事件信息的数据,再一个个生成新的event对象(注意需要给它标注一个flag,用于表示它是来自拷贝事件),放到 gameMap 里
3. 离开地图时,把全部有flag的事件再提取它的信息,做成新的数组,覆盖全局变量中该地图对应的拷贝事件信息数组

而要在事件中调用事件拷贝,只需要把由拷贝事件信息生成新的event对象放到 gameMap 里这一步弄出一个接口,包装成比如注释调用、事件脚本调用就好了
作者: 2669483303    时间: 2023-6-30 03:12
YEP不是有现成的事件拷贝插件吗,如果不想用也可以参考下代码
作者: 小怪兽奇奇侠    时间: 2023-6-30 12:15
我不是大佬,但我还是进来了,不要打我
作者: zazny    时间: 2023-7-7 22:54
其实题主的代码可能还存在一些其他问题
js中的深拷贝是不能直接把json中运行的function拷贝过来的,也就是说题主的代码只是拷贝了数据,事件本身不会被拷贝,同时数据还占用了事件数列的位置,可能产生错误
解决方法的话,本人只研究过MZ代码但mv应该同理
1.拷贝时直接获取地图的原数据(如data目录下的Map001.json文件)
2.获取事件对应的json
3.修改event的编号(很重要)
4.上代码:
//1.create in $dataMap
  let i=$gameMap._events.length
  $dataMap.events[i]={...}
//2.add it to $gameMap
  $gameMap._events[i]=new Game_Event(mapid,i)
//3.refresh
  $gameMap.refreshTileEvents()
作者: zazny    时间: 2023-7-7 22:56
另外题主的代码也可能是异步的问题,建议使用es6标准里的 await async或者es5里的 promise
作者: 任小雪    时间: 2023-7-8 01:53
zazny 发表于 2023-7-7 22:56
另外题主的代码也可能是异步的问题,建议使用es6标准里的 await async或者es5里的 promise ...

大佬们是真的强(因为我真的是俺寻思党,不知道这次能学到多少),唔,我现实里的破工作暂时甚至出了点问题,暂时没心思研究这个,唉(话说,我其实还是有点怀疑仅是引擎本事机能限制的问题而已,怎么说呢,我有一张摆家具的地图,里面221个家具事件都显示图像的话,貌似是有点感觉卡的,当初刚好测试的时候)
作者: 任小雪    时间: 2023-7-13 00:39
zazny 发表于 2023-7-7 22:54
其实题主的代码可能还存在一些其他问题
js中的深拷贝是不能直接把json中运行的function拷贝过来的,也就是 ...

大佬的法子貌似类似于鹿大佬之前给我的法子(我的好像是前一两个帖子问过的),但有一两个问题,一个是不切换场景(比如开关一次菜单),角色无法刷新;一个是,角色头上原带有的名字没有复制显示出来(我自己俺寻思出来的插件(脚本),利用了原本地图名字显示的代码,改造了一下后,强行塞了些脚本进去)
作者: 任小雪    时间: 2023-7-19 22:03
小秋橙 发表于 2023-6-29 04:16
// 启动时加载所有地图到$dataMapInfos,以后切换地图时直接取用结果
let loadDatabase = DataManager.load ...

不知道大佬的代码对不对,我暂时还看不懂(不是说看不懂注释,是不能化为自己的姿势),所以,暂时不用了,但,貌似大佬的答案最高深,就给最佳答案吧
然后,我找到了我卡的一大部分原因了,主要是我自己弄到实时小地图插件占了8、9成卡的原因(我帖子里说到的代码,应该还是非一直执行的,有无镶套就不知道了)。
我的部分报错的原因(这个贴子里好像没说过,应该跟我$dataMap和$gameMap的使用有关,唔,貌似$dataMap是根本,而$gameMap是实时的……)




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1