设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1331|回复: 18
打印 上一主题 下一主题

[有事请教] 【大佬请进】我利用Game_Event.prototype.event = function() {做了shi...

[复制链接]

Lv3.寻梦者

梦石
0
星屑
2856
在线时间
446 小时
注册时间
2016-9-26
帖子
1222
跳转到指定楼层
1
发表于 2023-6-29 04:15:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1000星屑
本帖最后由 任小雪 于 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. };

最佳答案

查看完整内容

// 启动时加载所有地图到$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.js ...

Lv4.逐梦者

梦石
0
星屑
5923
在线时间
423 小时
注册时间
2021-12-4
帖子
464
2
发表于 2023-6-29 04:16:00 | 只看该作者
// 启动时加载所有地图到$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 23:25
回复

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3956
在线时间
168 小时
注册时间
2021-3-31
帖子
201
3
发表于 2023-6-29 08:00:30 | 只看该作者
看看实现过程,确定是不是跟多个事件有关,另外是否存在持续进行的并行事件在持续调用event()

点评

LCH.是我自己的变量,我不是使用公共变量的  发表于 2023-6-29 12:46
代码发了,唔,虽然对于大佬们看起来肯定很不友好(指阅读方面)  发表于 2023-6-29 12:43
mv/mz系列插件定制/修改/移植
mv/mz spine系列插件出售
mz底层取代中,webgpu/webgl即将同时启动
个人QQ2311993475,有需求注明来意
回复

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3956
在线时间
168 小时
注册时间
2021-3-31
帖子
201
4
发表于 2023-6-29 08:08:31 | 只看该作者
另外,你说你是在执行完事件之后存档,那么你去检查下对应的$dataMap的数据中的events一项,该项是否过于复杂或者嵌套,在当前地图检索当前地图的events()
$gameMap.events()以及在是否有异常,地图会每帧执行事件刷新指令,以检索是否有事件达到条件执行
mv/mz系列插件定制/修改/移植
mv/mz spine系列插件出售
mz底层取代中,webgpu/webgl即将同时启动
个人QQ2311993475,有需求注明来意
回复

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
186
在线时间
45 小时
注册时间
2023-6-26
帖子
5
5
发表于 2023-6-29 14:17:31 | 只看该作者
不会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:07
回复

使用道具 举报

Lv6.析梦学徒

老鹰

梦石
40
星屑
33609
在线时间
6577 小时
注册时间
2012-5-26
帖子
3186

极短24评委极短23参与极短22参与极短21评委老司机慢点开短篇十吟唱者组别冠军开拓者剧作品鉴家

6
发表于 2023-6-29 22:09:09 | 只看该作者
本帖最后由 百里_飞柳 于 2023-6-29 22:16 编辑

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

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

而要在事件中调用事件拷贝,只需要把由拷贝事件信息生成新的event对象放到 gameMap 里这一步弄出一个接口,包装成比如注释调用、事件脚本调用就好了

点评

因为小地图功能和显示名字的功能我需要用到事件的meta  发表于 2023-6-29 22:38
我的变量LCH.Map_Freshed的用法不能让它只执行一次吗?主要是,不在这里这样弄,在别的地方弄貌似都会出现报错的情况  发表于 2023-6-29 22:35
回复

使用道具 举报

Lv2.观梦者

梦石
0
星屑
811
在线时间
117 小时
注册时间
2018-8-25
帖子
95
7
发表于 2023-6-30 03:12:29 | 只看该作者
YEP不是有现成的事件拷贝插件吗,如果不想用也可以参考下代码
回复

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
10855
在线时间
2043 小时
注册时间
2013-6-10
帖子
1504
8
发表于 2023-6-30 12:15:19 | 只看该作者
我不是大佬,但我还是进来了,不要打我
回复

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
112
在线时间
11 小时
注册时间
2021-4-27
帖子
6
9
发表于 2023-7-7 22:54:03 | 只看该作者
其实题主的代码可能还存在一些其他问题
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()
回复

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
112
在线时间
11 小时
注册时间
2021-4-27
帖子
6
10
发表于 2023-7-7 22:56:19 | 只看该作者
另外题主的代码也可能是异步的问题,建议使用es6标准里的 await async或者es5里的 promise
回复

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-6-15 11:27

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表