不知道有人遇到过这种情况没有,在一张地图上画一座桥,但是要求角色在桥上能够通过,也能够在桥下穿行,就像下图这样:
仔细想想就发现直接绘制有困难,因为无论怎么设置地图元件的通过规则,似乎都很难实现这一效果,为此不得不动用脚本,但是又不希望它太复杂,因此除了少数用脚本实现的功能以外,剩下的就靠数据库编辑器和事件编辑器处理。
思路:造成通过规则不同的原因就是角色所在的“高度”和桥所在的“高度”不同,而无论是在数据库中还是脚本中,RGSS1均没有高度的概念,只要坐标相等就被判定是同一层的东西。因此也会出现一些奇怪的现象,例如说主角站在较低的地方可以激活较高地方的事件,原因还是RGSS1不区分哪里是悬崖,哪里是平地,只要坐标相同或者相邻,就会判定事件启动。因此,我们需要弄一些开关来决定主角到底在“第几层”。
步骤一:
首先我们要做一些准备工作,插入一些脚本,以便我们处理问题的方便,首先便是这个脚本:
- class Game_Map attr_accessor :new_tileset alias old_setup setup def setup(map_id) @new_tileset = false old_setup(map_id) end def replace_tileset(new_tiles) tileset = $data_tilesets[new_tiles] @tileset_name = tileset.tileset_name @autotile_names = tileset.autotile_names @panorama_name = tileset.panorama_name @panorama_hue = tileset.panorama_hue @fog_name = tileset.fog_name @fog_hue = tileset.fog_hue @fog_opacity = tileset.fog_opacity @fog_blend_type = tileset.fog_blend_type @fog_zoom = tileset.fog_zoom @fog_sx = tileset.fog_sx @fog_sy = tileset.fog_sy @battleback_name = tileset.battleback_name @passages = tileset.passages @priorities = tileset.priorities @terrain_tags = tileset.terrain_tags $game_map.new_tileset = true endendclass Spriteset_Map alias old_update update def update if $game_map.new_tileset == true @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name) @tilemap.priorities = $game_map.priorities for i in 0..6 autotile_name = $game_map.autotile_names[i] @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name) end $game_map.new_tileset = false end old_update endend复制代码
复制代码这段脚本的意思是替代当前地图的所有地图图块,实际上就是用脚本的方法手动修改这里:
我们将这个脚本插入到Main之前,或者懂脚本的朋友可以直接在原脚本上进行直接插入。有了这一步作为基础,我们就可以进行下面的操作。
步骤二:
刚才我们说到,没有办法在一个地图中,将一个元件设置为两种通行的规则,那我们就用两个,假如我们用的地形是[山道],那么我们要将它再复制一份。在这里我们看到,原来的[山道]地图,桥的通行规则是按照主角行走在桥上设计的,即不能再桥下穿行,那么这个复制的地形,我们将桥设置为能在桥下穿行的情况,就像这样:
不要忘记设置优先度和通行方向。接下来我们做的就是在两种地形之间的切换。
步骤三:
两种地形之间的切换多半发生在梯子处,因此我们要建立一个事件放在梯子上面,事件的内容很简单,如图:
在这里,需要说明的是$game_map.replace_tileset(id)的用法,是用编号ID为id的图块(数据库中)来替换当前的图块。我们刚才在图中看到,修改后的地图为[山道2],在数据库中的ID为51,因此要使用这一句脚本。另外,对角色面向进行分歧判断也是必要的,也就是说“上楼”和“下楼”都要进行地图的替换。那个开关[0001:Level 2]表示的是主角是否在上面一层的开关,现在我们看不到它的作用,在后面我们会了解。将整个事件放在楼梯的地方,注意所有的楼梯都要放置。
这样,我们的主角就能自由在桥上桥下穿梭了。
问题:这样的做法似乎没有什么不妥之处,不过仔细思考一下就会发现它其实是有问题的,原因在于这样定义的临时更改地形的方法无法被保存下来,导致存盘之后再读取,程序不会自动装载合适的地形,因此我们要修改一下Scene_Load:
- class Scene_Load def read_save_data(file) # 读取描绘存档文件用的角色数据 characters = Marshal.load(file) # 读取测量游戏时间用画面计数 Graphics.frame_count = Marshal.load(file) # 读取各种游戏对像 $game_system = Marshal.load(file) $game_switches = Marshal.load(file) $game_variables = Marshal.load(file) $game_self_switches = Marshal.load(file) $game_screen = Marshal.load(file) $game_actors = Marshal.load(file) $game_party = Marshal.load(file) $game_troop = Marshal.load(file) $game_map = Marshal.load(file) $game_player = Marshal.load(file) # 魔法编号与保存时有差异的情况下 # (加入编辑器的编辑过的数据) if $game_system.magic_number != $data_system.magic_number # 重新装载地图 $game_map.setup($game_map.map_id) ### 修改 if $game_switches[1] == true $game_map.replace_tileset(4) if $game_map.map_id == 1 end ### 修改完毕 $game_player.center($game_player.x, $game_player.y) end # 刷新同伴成员 $game_party.refresh endend复制代码
复制代码注意修改的部分,实际上是指如果读档之后,发现主角的层数在第二层,那么就按照地图ID自动装载新的地形。刚才我们说到,开关[0001:Level 2]就是表示主角是否在上层,因此先做一步判断,如果主角在上层,那么就进行地形的替换,刚才那个地图的ID是1,第二层的地形是[004:山道],因此如果是在1号地图上,地形将自动替换为山道的2层图块。这也就是为什么我们要设置一个开关来表示主角在上层还是在下层。注意,主角刚刚进入地图时在上下层是由写程序的人决定的,如果一开始进入地图中就已经是上层了,那么就应该在桥的入口处再放置一个事件即可。
另外,这个机制能够解决“隔悬崖开宝箱”的问题,只需要给宝箱设置两个事件页,第一个事件页只放置宝箱图片,第二个事件页的出现条件设置为开关上层为On即可。
不足之处:这种方法只能处理只有两层的地图,如果上层的平台上面还有一层,并且这一层也有桥,那么这个方法就没法处理了。究其原因,是在第二层中,桥的通过属性变成了两种,而且要同时成立,因此不能用这种方法。
本帖来自P1论坛作者紫英晓狼1130,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:
https://rpg.blue/forum.php?mod=viewthread&tid=354578 若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。