Project1

标题: 有关菜单active属性的设置 [打印本页]

作者: mike1735    时间: 2014-2-9 02:32
标题: 有关菜单active属性的设置
同一个画面有两个菜单,左选项菜单,右人物菜单。通过人物菜单可以进入人物的装备,技能等rm自带的菜单。
从装备等菜单返回的时候,默认是开启左菜单,冻结有菜单。我想返回的时候冻结做菜单,返回有菜单,如何设定?
由于不知道发帖的时候怎么贴图和代码,我会把图和代码贴在回复上。
作者: mike1735    时间: 2014-2-9 02:45
我的想法是在Scene_MenuBase里建一个@last_scene变量,
当进入skill等菜单时,@last_scene被赋值为3,当进入选项菜单时被赋值为1。这样只要判断这个变量是否为3可知玩家是从地图场景进入下图的菜单界面的,还是通过skill等菜单退回到如下的菜单界面的。
由此来决定是开启左菜单还是右菜单。可是我失败了。我发现如果把这个变量变为全局变量是可行的,这是为什么?或者大家还有没有其他好方法?
  1. class Scene_Menu < Scene_MenuBase
  2. #----------------------

  3. #---------------------
  4. #----------------------------------------------------------------------------
  5.   # * 创建菜单选项
  6.   #----------------------------------------------------------------------------
  7.   def create_menu_command
  8.     @menu_command = Window_MenuCommand.new
  9.     @menu_command.set_handler(:cancel, method(:return_scene))
  10.     @menu_command.set_handler(:item, method(:item_ok))
  11.     @menu_command.set_handler(:skill, method(:person_ok))
  12.     @menu_command.set_handler(:equip, method(:person_ok))
  13.     @menu_command.set_handler(:status, method(:person_ok))
  14.     @menu_command.set_handler(:formation, method(:person_ok))
  15.     @menu_command.set_handler(:save, method(:save_ok))
  16.     @menu_command.set_handler(:load, method(:load_ok))
  17.     @menu_command.set_handler(:game_end, method(:end_ok))
  18.     @menu_command.active = (@last_scene != 3 ? true : false)
  19.     @menu_command.select(@last_index)
  20.     @menu_command.opacity = 0
  21.   end
  22.   #-----------------------------------------------------------------------------
  23.   #  *创建人物状态菜单
  24.   #-----------------------------------------------------------------------------
  25.   def create_menustatus_command
  26.     @menustatus_command = Window_NewMenuStatus.new
  27.     @menustatus_command.active = (@last_scene == 3 ? true : false)
  28.     @menustatus_command.set_handler(:cancel, method(:back_command))
  29.     @menustatus_command.set_handler(:ok, method(:status_ok))
  30.     @menustatus_command.select(@last_index2)
  31.     @menustatus_command.opacity = 0
  32.   end
复制代码
  1. class Scene_Skill < Scene_ItemBase
  2.   #--------------------------------------------------------------------------
  3.   # ● 开始处理
  4.   #--------------------------------------------------------------------------
  5.   def start
  6.     super
  7.     create_help_window
  8.     create_command_window
  9.     create_status_window
  10.     create_item_window
  11.     @last_scene = 3
  12.   end
复制代码
  1. class Scene_MenuBase < Scene_Base
  2.   #-----------------------------------------------------------------------------
  3.   #    *初始化
  4.   #-----------------------------------------------------------------------------
  5.   def initialize
  6.     super
  7.     @last_index = 0 if @last_index == nil
  8.     @last_index2 = 0 if @last_index2 == nil
  9.     @last_scene = 0 if @last_scene == nil
  10.   end
  11. end
复制代码

作者: 945127391    时间: 2014-2-9 05:34
VA可以直接使用
  1. SceneManager.return
复制代码
返回到前一个场景
作者: 余烬之中    时间: 2014-2-9 08:33
返回时使用SceneManager.return而不是SceneManager.call
作者: 千昭    时间: 2014-2-9 09:15
楼主想的真复杂
作者: mike1735    时间: 2014-2-9 13:23
我的设想是:地图场景→场景1:技能→人物→场景2:技能菜单。(从地图进入菜单先冻结右边的菜单)回来的时候:场景2:技能菜单→场景1:人物→技能→地图场景(就是说从技能菜单回来先冻结的是左边的菜单)。可现在是这样的:场景2:技能菜单→场景1:技能→地图场景(和从地图进入菜单一样冻结了右边的菜单),我就想设置一下相应情况左菜单和右菜单的active属性。不是转换场景的问题。
作者: 喵呜喵5    时间: 2014-2-9 13:40
首先是关于你说的那个为什么用实例变量不可行而用全局变量可行的问题……
打开菜单实际上是打开一个菜单实例,切换到其他界面的时候这个菜单实例就被干掉了,实例变量自然无法保留
用局部变量来类比的话差不多是这样:
  1. def mwm5
  2.   jiecao = 0
  3. end
  4. def mwm6
  5.   p jiecao
  6. end
复制代码
上面两个方法,即使执行了mwm5以后执行mwm6结果还是nil,局部变量这个方法结束以后就被干掉了,实例变量这个实例释放以后就被干掉了,一个道理

然后全局变量不会因为实例的释放而被干掉,应该说怎么都干不掉……所以自然能满足你的要求

其他更好的方法的话,你可以试试使用类变量,具体的应用的话原生的脚本中记录菜单的选项位置那块有使用到,或者你也可以上网查查类变量的用法什么的,不过我自己感觉类变量完全没有全局变量用起来方便所以你自己考虑吧……
作者: 喵呜喵5    时间: 2014-2-9 14:00
本帖最后由 喵呜喵5 于 2014-2-9 14:25 编辑


唔,最后直接上脚本
没有经过太详细的测试,不保证百分百没有BUG
  1. class Window_MenuCommand  
  2.   def self.read_command_position
  3.     @@last_command_symbol
  4.   end
  5. end
  6. class Scene_Menu
  7.   alias m5_start start
  8.   def start
  9.     m5_start
  10.     symbol = Window_MenuCommand.read_command_position   
  11.     if symbol == :skill or symbol == :equip or symbol == :status      
  12.       @command_window.deactivate      
  13.       command_personal      
  14.     end   
  15.   end
  16. end
复制代码

作者: 喵呜喵5    时间: 2014-2-9 14:09
余烬之中 发表于 2014-2-9 08:33
返回时使用SceneManager.return而不是SceneManager.call

会被干掉啊?
原生脚本用的都是SceneManager.return返回上一个场景,不使用类变量连菜单的光标都无法保留啊?
作者: 余烬之中    时间: 2014-2-9 14:41
喵呜喵5 发表于 2014-2-9 14:09
会被干掉啊?
原生脚本用的都是SceneManager.return返回上一个场景,不使用类变量连菜单的光标都无法保留 ...

楼主显然是这种情况:呼叫通过set_handler指定的方法激活了人物菜单 然后SceneManager.call呼出更详细的界面(比如某个角色的技能列表)
  1.   def self.call(scene_class)
  2.     @stack.push(@scene)
  3.     [url=home.php?mod=space&uid=420706]@Scene[/url] = scene_class.new
  4.   end

  5.   def self.return
  6.     @scene = @stack.pop
  7.   end
复制代码
这样的话存储结构大概可以这样描述
@stack == [Scene_Menu的实例, Scene_Map的实例, SceneTitle的实例……]
@scene == Scene_Skill的实例
pop的时候会重新new吗?

我写着写着突然顿悟了 根本不需要重新new 但是我们要的不是new……Scene里面起作用的是start 跟随main执行………………
作者: mike1735    时间: 2014-2-9 19:12
余烬之中 发表于 2014-2-9 14:41
楼主显然是这种情况:呼叫通过set_handler指定的方法激活了人物菜单 然后SceneManager.call呼出更详细 ...

这个问题我用实例变量解决了。但还有一个问题。首先VA本身用的就是return,我没改。如下。而且看我上面的代码,为了记录光标的位置我用了@last_index(2)来记录。从你给的那段代码来看在切场景的时候是把上个场景实例放到了栈里,return直接提取上个实例,那么的确应该像你说的保留上个菜单的状态,但事实并非如此(不记录的话会重置)。为什么?
  1.   def create_command_window
  2.     wy = @help_window.height
  3.     @command_window = Window_SkillCommand.new(0, wy)
  4.     @command_window.viewport = @viewport
  5.     @command_window.help_window = @help_window
  6.     @command_window.actor = @actor
  7.     @command_window.set_handler(:skill,    method(:command_skill))
  8.     @command_window.set_handler(:cancel,   method(:return_scene))
  9.     @command_window.set_handler(:pagedown, method(:next_actor))
  10.     @command_window.set_handler(:pageup,   method(:prev_actor))
  11.   end
复制代码

作者: mike1735    时间: 2014-2-9 19:20
这个问题我用类变量解决了。但我还有个问题。首先我确实使用的return。如下。而且为了记录光标位置我用了@last_index。但是从你给的代码来看在切场景的时候VA把上一个场景实例放到栈里。return提取栈里的最后一个实例,那么确实应该保持菜单状态。可事实不是这样(不记录的话会重置)。为什么?
  1.   def create_command_window
  2.     wy = @help_window.height
  3.     @command_window = Window_SkillCommand.new(0, wy)
  4.     @command_window.viewport = @viewport
  5.     @command_window.help_window = @help_window
  6.     @command_window.actor = @actor
  7.     @command_window.set_handler(:skill,    method(:command_skill))
  8.     @command_window.set_handler(:cancel,   method(:return_scene))
  9.     @command_window.set_handler(:pagedown, method(:next_actor))
  10.     @command_window.set_handler(:pageup,   method(:prev_actor))
  11.   end
复制代码

作者: mike1735    时间: 2014-2-9 19:22
余烬之中 发表于 2014-2-9 14:41
楼主显然是这种情况:呼叫通过set_handler指定的方法激活了人物菜单 然后SceneManager.call呼出更详细 ...

这个问题我用类变量解决了。但我还有个问题。首先我确实使用的return。如下。而且为了记录光标位置我用了@last_index。但是从你给的代码来看在切场景的时候VA把上一个场景实例放到栈里。return提取栈里的最后一个实例,那么确实应该保持菜单状态。可事实不是这样(不记录的话会重置)。为什么?
  1.   def create_command_window
  2.     wy = @help_window.height
  3.     @command_window = Window_SkillCommand.new(0, wy)
  4.     @command_window.viewport = @viewport
  5.     @command_window.help_window = @help_window
  6.     @command_window.actor = @actor
  7.     @command_window.set_handler(:skill,    method(:command_skill))
  8.     @command_window.set_handler(:cancel,   method(:return_scene))
  9.     @command_window.set_handler(:pagedown, method(:next_actor))
  10.     @command_window.set_handler(:pageup,   method(:prev_actor))
  11.   end
复制代码

作者: 喵呜喵5    时间: 2014-2-9 19:34
mike1735 发表于 2014-2-9 19:20
这个问题我用类变量解决了。但我还有个问题。首先我确实使用的return。如下。而且为了记录光标位置我用了@l ...

他最后不都说了吗

栈里保存的是scene的实例,而你储存实例变量的是window的实例,window的实例在切换场景的时候自动释放掉了
作者: 余烬之中    时间: 2014-2-9 19:40
mike1735 发表于 2014-2-9 19:20
这个问题我用类变量解决了。但我还有个问题。首先我确实使用的return。如下。而且为了记录光标位置我用了@l ...


我们知道 场景类一般会调用create_command_window来创建命令窗口
这个方法里面一定有一句@some_window = Window_Something.new(perhaps args)
如果这个语句只执行一次 那么显然会保存位置
但是场景每次出现都会执行 因为
RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2.   # ● 主逻辑
  3.   #--------------------------------------------------------------------------
  4.   def main
  5.     start
  6.     post_start
  7.     update until scene_changing?
  8.     pre_terminate
  9.     terminate
  10.   end
上面这一段来自Scene_Base
RUBY 代码复制
  1. def start
  2.     super
  3.     create_command_window
  4.     create_gold_window
  5.     create_status_window
  6.   end
这一段来自Scene_Menu
所以 尽管场景类还是原来的(压栈退栈) 但是窗口已经被重新创建了
而选择的位置是保存在窗体实例中的
所以 选择位置不能是实例变量 而必须是全局或者类变量
由此易知 如果退出场景时  选择位置保存在场景实例中 就不需要类变量了
作者: tan12345    时间: 2014-2-9 20:00
问的东西貌似和active没关啊……
其实VA默认的界面分2种,一种叫窗口(window),一种叫界面(scene),如果是同一个界面的左右窗口的激活与冻结,直接window.activate和window.deactivate就好了啊,如果是界面之间的切换,那才需要SceneManager.push和SceneManager.return




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