查看: 85|回复: 0

[转载发布] 【教程】制作一个Mogeko Castle式的菜单界面

[复制链接]
  • TA的每日心情
    开心
    前天 00:56
  • 签到天数: 33 天

    连续签到: 1 天

    [LV.5]常住居民I

    2022

    主题

    32

    回帖

    7144

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    0
    卡币
    5074
    OK点
    16
    积分
    7144
    发表于 同元一千年二月十八日(春) | 显示全部楼层 |阅读模式
    庆祝我的博客搬家,把我七年前写了一半的教程写完了……

    访问我的博客获得更好的阅读体验 https://script.miaowm5.com/post/93

    引言


    前一段时间玩了海底囚人的 Mogeko Castle ,虽然电波对不上玩起来感觉有点微妙,但是这个游戏使用的菜单还是有点意思的。因此,打算写一个简单的教程介绍一下如何使用RMVA制作出这样的菜单。请注意,下面的教程要求你有一定的脚本基础,整个教程我更多的是说明我写这个脚本时的思路而不是为什么可以这么写,因此……嘛。
    首先先放上游戏菜单的截图:


    另外,随着游戏进程的推进或者游戏中加入新角色时,菜单中的立绘和人物信息还会发生改变,例如下面这样:


    大概搞懂了需求以后,下面就开始开心的写代码吧。

    调整已有逻辑


    首先,先在 Window_MenuCommand 中删除菜单不需要的选项。
    这里保留了 add_original_commands 以增强和其他菜单添加选项脚本的兼容性。
    RUBY 代码
    1. class Window_MenuCommand
    2.   def make_command_list
    3.     add_command(Vocab::item, :item)
    4.     add_original_commands
    5.     add_save_command
    6.     add_game_end_command
    7.   end
    8. end
    复制代码

    接着,进入到 Scene_Menu 中,把不需要的右侧队友状态窗口删除。
    RUBY 代码
    1. class Scene_Menu
    2.   def create_status_window
    3.   end
    4. end
    复制代码

    注意到原本的菜单中这两个窗口并不是仅仅贴着屏幕边缘而是和其有一小段距离的,在 start 的最后将这两个窗口的位置稍微移动一些。
    RUBY 代码
    1. class Scene_Menu
    2.   alias m5_20150301_start start
    3.   def start
    4.     m5_20150301_start
    5.     @command_window.x += 6
    6.     @command_window.y += 6
    7.     @gold_window.x += 6
    8.     @gold_window.y -= 6
    9.   end
    10. end
    复制代码


    队伍成员窗口


    下面开始制作显示当前队伍成员的窗口,新建一个 Window_Base 的子类,起一个不容易冲突的名字 Window_M5ActorStatus20150301。最开始先要快速测试窗口是否正常显示,因此先把随便把位置定在 200,200,大小设置为 160*100
    RUBY 代码
    1. class Window_M5ActorStatus20150301 < Window_Base
    2.   def initialize
    3.     super(200,200,160,100)
    4.   end
    5. end
    复制代码

    将上述窗口加到 Scene_Menu 中
    RUBY 代码
    1. class Scene_Menu
    2.   alias m5_20150301_start start
    3.   def start
    4.     m5_20150301_start
    5.     @command_window.x += 6
    6.     @command_window.y += 6
    7.     @gold_window.x += 6
    8.     @gold_window.y -= 6
    9.     @m5_20220418_actor_window = Window_M5ActorStatus20150301.new
    10.   end
    11. end
    复制代码

    总体来看似乎没有什么大问题,接下去就开始为窗口内部描绘内容了。先从描绘队伍中第一个角色开始。重新修改 Window_M5ActorStatus20150301 添加描绘行走图和名字的代码。
    同时,根据游戏内实际的表现,开始细调内容的位置和窗口的尺寸位置。最终的窗口大小为 160*70,位置为 6,286。
    RUBY 代码
    1. class Window_M5ActorStatus20150301 < Window_Base
    2.   def initialize
    3.     x = 6
    4.     y = 286
    5.     width = 160
    6.     height = 70
    7.     actor = $game_party.leader
    8.     super(x,y,width,height)
    9.     refresh(actor)
    10.   end
    11.   def refresh(actor)
    12.     contents.clear
    13.     draw_actor_graphic(actor, 20, 40)
    14.     draw_text(0, 0, contents_width, line_height, actor.name, 2)
    15.   end
    16. end
    复制代码

    第一个角色调通后,下面该开始根据队伍中的实际数据显示角色了。重新改写 Window_M5ActorStatus20150301 的代码
    RUBY 代码
    1. class Window_M5ActorStatus20150301 < Window_Base
    2.   def initialize(actor, index)
    3.     x = 6
    4.     y = 286 - index * (70 + 5)
    5.     width = 160
    6.     height = 70
    7.     super(x,y,width,height)
    8.     refresh(actor)
    9.   end
    10.   def refresh(actor)
    11.     contents.clear
    12.     draw_actor_graphic(actor, 20, 40)
    13.     draw_text(0, 0, contents_width, line_height, actor.name, 2)
    14.   end
    15. end
    复制代码

    Window_M5ActorStatus20150301 里,窗口的 y 坐标从固定的286改成第一个窗口286,第二个窗口286-70+5,第三个窗口286-(70+5)*2……依次类推。(70 是窗口的高度,5 是窗口和窗口的间距。)窗口描绘的角色也从固定的 $game_party.leader 修改成了通过参数传递。
    接下来,修改 Scene_Menu ,将 Window_M5ActorStatus20150301 所需的 actor 和 index 传递进去。
    RUBY 代码
    1. class Scene_Menu
    2.   alias m5_20150301_start start
    3.   def start
    4.     m5_20150301_start
    5.     @command_window.x += 6
    6.     @command_window.y += 6
    7.     @gold_window.x += 6
    8.     @gold_window.y -= 6
    9.     @m5_20220418_actor_window = $game_party.all_members.slice(0,3)
    10.       .reverse.collect.each_with_indexdo |actor, index|
    11.         Window_M5ActorStatus20150301.new(actor, index)
    12.       end
    13.   end
    14.   instance_methods(false).include?(:terminate) ||
    15.     (def terminate *args; super; end)
    16.   alias m5_20220418_terminate terminate
    17.   def terminate
    18.     m5_20220418_terminate
    19.     @m5_20220418_actor_window.each(&:dispose)
    20.   end
    21. end
    复制代码

    ……似乎写了一段很吓人的代码,我们一点点分析这次做出的改动。
    1. @m5_20220418_actor_window = $game_party.all_members.slice(0,3)  .reverse.collect.each_with_index do |actor, index|    Window_M5ActorStatus20150301.new(actor, index)  end复制代码
    复制代码
    @m5_20220418_actor_window 不再是窗口了,现在变成了一个数组。我们先通过 $game_party.all_members 获取到当前队伍中全部的角色,再通过 slice(0,3) 选择前三个角色,之后,使用 reverse 方法反转顺序,最后使用 collect 方法将每个角色作为参数传递给 Window_M5ActorStatus20150301,最终返回的窗口被放入了数组中。通过上面这一串操作,最终成功达成了根据队伍中当前成员情况动态创建窗口的目的。
    同时,因为 @m5_20220418_actor_window 不再是窗口而是数组了,数组中的窗口不再会自动释放了,因此,我们需要手动在界面关闭时调用每个窗口的 dispose 方法
    1. alias m5_20220418_terminate terminatedef terminate  m5_20220418_terminate  @m5_20220418_actor_window.each(&:dispose)end复制代码
    复制代码
    另外,在默认脚本中 Scene_Menu 并没有定义 terminate 方法,出于 alias 的兼容性考虑,我们还需要显式的定义一下。
    1. instance_methods(false).include?(:terminate) ||  (def terminate *args; super; end)复制代码
    复制代码
    大功告成!

    立绘展示


    完成了角色信息弹窗,接下来就开始写界面右侧立绘展示的代码了。在开始写代码之前我们先规划一下这个功能的设计。对于角色立绘的展示,我们打算换一种方式,直接根据 变量1 的值确定立绘显示的内容。
    我们先准备素材,这次的素材选择的是 MtU@ついった 老师画的结月缘,为了方便对坐标,这次直接将素材尺寸处理成屏幕的 544*416 大小,将素材放到 Graphics/Pictures/menu_actor 下面。
    接下来,继续改写 Scene_Menu ,加上用于显示立绘的 Sprite 的创建和释放代码。
    1. class Scene_Menu  def start    m5_20150301_start    @command_window.x += 6    @command_window.y += 6    @gold_window.x += 6    @gold_window.y -= 6    @m5_20220418_actor_window = $game_party.all_members.slice(0,3)      .reverse.collect.each_with_index do |actor, index|        Window_M5ActorStatus20150301.new(actor, index)      end    @m5_20220418_actor_sprite = Sprite.new    @m5_20220418_actor_sprite.bitmap = Cache.picture('menu_actor/0')  end  def terminate    m5_20220418_terminate    @m5_20220418_actor_window.each(&:dispose)    @m5_20220418_actor_sprite.dispose  endend复制代码
    复制代码
    显示正常了,接下来就改写代码,让图片能够根据变量1的值动态的显示不同的立绘吧。
    1. @m5_20220418_actor_sprite.bitmap = Cache.picture("menu_actor/#{$game_variables[1]}")复制代码
    复制代码
    大功告成!

    最终成品


    RUBY 代码
    1. class Window_MenuCommand
    2.   def make_command_list
    3.     add_command(Vocab::item, :item)
    4.     add_original_commands
    5.     add_save_command
    6.     add_game_end_command
    7.   end
    8. end
    9. class Scene_Menu
    10.   alias m5_20150301_start start
    11.   def start
    12.     m5_20150301_start
    13.     @command_window.x += 6
    14.     @command_window.y += 6
    15.     @gold_window.x += 6
    16.     @gold_window.y -= 6
    17.     @m5_20220418_actor_window = $game_party.all_members.slice(0,3)
    18.       .reverse.collect.each_with_indexdo |actor, index|
    19.         Window_M5ActorStatus20150301.new(actor, index)
    20.       end
    21.     @m5_20220418_actor_sprite = Sprite.new
    22.     @m5_20220418_actor_sprite.bitmap = Cache.picture("menu_actor/#{$game_variables[1]}")
    23.   end
    24.   def create_status_window
    25.   end
    26.   instance_methods(false).include?(:terminate) ||
    27.     (def terminate *args; super; end)
    28.   alias m5_20220418_terminate terminate
    29.   def terminate
    30.     m5_20220418_terminate
    31.     @m5_20220418_actor_window.each(&:dispose)
    32.     @m5_20220418_actor_sprite.dispose
    33.   end
    34. end
    35. class Window_M5ActorStatus20150301 < Window_Base
    36.   def initialize(actor, index)
    37.     x = 6
    38.     y = 286 - index * (70 + 5)
    39.     width = 160
    40.     height = 70
    41.     super(x,y,width,height)
    42.     refresh(actor)
    43.   end
    44.   def refresh(actor)
    45.     contents.clear
    46.     draw_actor_graphic(actor, 20, 40)
    47.     draw_text(0, 0, contents_width, line_height, actor.name, 2)
    48.   end
    49. end
    复制代码


                 本帖来自P1论坛作者小怪兽奇奇侠,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=489404  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
    天天去同能,天天有童年!
    回复 论坛版权

    使用道具 举报

    ahome_bigavatar:guest
    ahome_bigavatar:welcomelogin
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2024-4-30 11:13 , Processed in 0.046767 second(s), 41 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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