Project1

标题: 【教程】解决调用事件菜单NPC等物还会动的问题。 [打印本页]

作者: 玄月    时间: 2009-1-28 09:08
标题: 【教程】解决调用事件菜单NPC等物还会动的问题。
    麻烦各位老板看帖留下建议或者这个可以改进的地方。哈啦…………
[LINE]1,#dddddd[/LINE]
    第一次写这类教程。因为也算不上教程。因为改动的地方也不多。我跟精灵说,这样的教程可能已经有了。那我也没必要再来寒暄了。可是,又想了想。其实可能本来有也很难找着了。那我还是来写着教程吧。看得顺眼的,认为对你有帮助的来签下名。觉得这篇教程没什么实际作用的鸡蛋还是什么都没所谓。尽管飞吧。寒暄就到此结束。
[LINE]1,#dddddd[/LINE]
    首先我们知道,事件只能在地图上面调用。在菜单啊,技能啊之类的场景是不能调用的。因为地图上有关于调用事件的代码,而菜单之类的没有。
    这是个恒久的问题了。以前发布我游戏的测试版的时候,TT和剑也说,调用事件菜单的时候那些NPC啊,怪啊,笨鸟之类的还在乱跑乱飞。显得很诡异。黑剑1也有这问题,存完档怪物们就杀到跟前了。那天上飞的鸟一个不小心乱放炮蛋炸下来怎么怎么办?那就呜呼哀哉了。
    本教程需要准备的材料有。已经做好的事件菜单和新开的RM工程。
    新建一个RM工程,按下F11打开脚本编辑器。我们可以看见一堆脚本,不用管它。拖到最下,我们看到十几个Scene_XXX。我们可以看见有Scene_Title,Scene_Menu还有Scene_Map之类的。这次的主角是Scene_Map。你看既然Scene_Map和Scene_Menu一样都是场景,那么他们就肯定格式是一样的。那么为什么我们可以在Scene_Map这个场景中跑来跑去呢?原因就是位图的连续刷新。关于这个我们等一下再说。
    首先把Scene_Map脚本复制一遍,然后改名,叫什么都可以。接下来我们把无用的东西都删掉。呼啦啦呼啦啦。至于什么要删掉呢?就是调用战斗调用菜单之类的。也就是102行之下所有的。删完之后别忘了加上两个end,一个是updata的,一个是class的。
    删完之后我们就得到以下的脚本,名字我暂时就叫他Scene_EventMenu好了(事件菜单XXD)
   
  1. #==============================================================================
  2. # ■ Scene_Map
  3. #------------------------------------------------------------------------------
  4. #  处理地图画面的类。
  5. #==============================================================================

  6. class Scene_EventMenu
  7.   #--------------------------------------------------------------------------
  8.   # ● 主处理
  9.   #--------------------------------------------------------------------------
  10.   def main
  11.     # 生成活动块
  12.     @spriteset = Spriteset_Map.new
  13.     # 生成信息窗口
  14.     @message_window = Window_Message.new
  15.     # 执行过渡
  16.     Graphics.transition
  17.     # 主循环
  18.     loop do
  19.       # 刷新游戏画面
  20.       Graphics.update
  21.       # 刷新输入信息
  22.       Input.update
  23.       # 刷新画面
  24.       update
  25.       # 如果画面切换的话就中断循环
  26.       if $scene != self
  27.         break
  28.       end
  29.     end
  30.     # 准备过渡
  31.     Graphics.freeze
  32.     # 释放活动块
  33.     @spriteset.dispose
  34.     # 释放信息窗口
  35.     @message_window.dispose
  36.     # 标题画面切换中的情况下
  37.     if $scene.is_a?(Scene_Title)
  38.       # 淡入淡出画面
  39.       Graphics.transition
  40.       Graphics.freeze
  41.     end
  42.   end
  43.   #--------------------------------------------------------------------------
  44.   # ● 刷新画面
  45.   #--------------------------------------------------------------------------
  46.   def update
  47.     # 循环
  48.     loop do
  49.       # 按照地图、实例、主角的顺序刷新
  50.       # (本更新顺序不会在的满足事件的执行条件下成为给予角色瞬间移动
  51.       #  的机会的重要因素)
  52.       $game_map.update
  53.       $game_system.map_interpreter.update
  54.       $game_player.update
  55.       # 系统 (计时器)、画面刷新
  56.       $game_system.update
  57.       $game_screen.update
  58.       # 如果主角在场所移动中就中断循环
  59.       unless $game_temp.player_transferring
  60.         break
  61.       end
  62.       # 执行场所移动
  63.       transfer_player
  64.       # 处理过渡中的情况下、中断循环
  65.       if $game_temp.transition_processing
  66.         break
  67.       end
  68.     end
  69.     # 刷新活动块
  70.     @spriteset.update
  71.     # 刷新信息窗口
  72.     @message_window.update
  73.   end
  74. end
复制代码

    然后接着刚才没讲完的话题。为什么人啊,鸟啊,怪啊可以在Scene_map里面动来动去什么时候心情不好就放两个炸弹给你享受。原因就是loop do在不断刷新他们的坐标和位图。精灵跟我说过一种方法。直接Graphics.freeze不就好了么。不过这种方法虽然看起来是没什么问题。可是他紧紧是把位图冻结了。可是人啊鸟啊怪啊的坐标还在改变。所以结束事件菜单的显示的时候就会来个瞬间移动给你。就好象罗罗的Geass一样,只是让你感官停止而已,可是实际上还是在动的。所以那炮弹该来的还是炸到你头上了。所以我们就把$game_map.update给注释或者删掉。
    这段脚本是干什么的呢?这个就是刷新整个地图的,包括人啊,鸟啊,怪啊,还有那颗新鲜的炸弹。注释掉他之后,人啊,鸟啊,怪啊都停止了。这才是真正的定身。都不动了,定住了。
    好了,基本的修改就到此为止了。或许有人会问:汝究竟改了什么?。我想说的就是。我仅仅删掉无用的东西而已。唉,事情就是这么简单。摊手。
    新的场景建立完了,然后我们就要调用公用事件中的菜单了。当然我们不能在事件中调用共用事件,因为这样在原来那个场景调用的公用事件会被新场景给取消掉。导致闪一下就没了的结果。
所以我们要在刚刚修改的脚本上面加一段代码。
详情参考6大的这个帖子http://rpg.blue/web/htm/news58.htm

    就是用脚本的方法调用公用事件。我们在Scene_EventMap这个脚本的主循环之前插入
  1. $game_temp.common_event_id = 1
复制代码
这段脚本。那个数字“1”是你要调用的公用事件编号。改成其他的也可以,只要是你的事件菜单的那个公用事件就可以了。然后还要进行一个小修改。不大,修改原来的Scene_Map.
用Ctrl+F搜索“● 调用菜单”不带引号。我们可以看见一个def call_menu。找到调用场景的那行。把$scene = Scene_Menu.new改成$scene = Scene_EventMenu.new。这个场景的名称就是我们刚刚修改的那一个场景的名称。
    至此,脚本的修改就完成了。然后转到公用事件的修改。
    公用事件改得也不多,就只是在菜单选项的最后一行加上一段脚本$scene = Scene_Map.new来返回场景。否则的话就算你点退出他还是会重新自动进入菜单。所以要插入一段脚本返回正常的地图场景。恩 END 了。谢谢大家看我发牢骚这么久。希望这个深得猥琐教授真传教程能对你的游戏制作之路提供帮助。
[LINE]1,#dddddd[/LINE]
    以下要补充一点东西,因为刚刚测试一遍发现了bug。就是如果在事件菜单中点选选项菜单之类的会使这个脚本该有的功能失去效果。那是因为在菜单中按下取消键是返回Scene_Map。所以就会出问题了。所以一些原本要返回Scene_Map的改为$scene = Scene_EventMenu.new就可以了。然后Scene_EventMenu也要修改一下。就是执行公用事件那一部分
  1. if $event == nil
  2.        $event = 0
  3.     end  
  4.     if $event == 0
  5.        $event = 1
  6.        $game_temp.common_event_id = 1
  7.     else
  8.     nil
  9.     end
复制代码
我们把它改成这样。为什么要改成这样呢。因为脚本菜单返回事件菜单的时候会重新执行了Scene.导致重新开始公用事件,这时候加上一个变量判定就可以了。这个变量名可以为其他的什么。最后别忘了公用事件最底下要把这个判定值变回0.否则就不能打开菜单了。
[LINE]1,#dddddd[/LINE]
这是我新建的那个场景的源代码
  1. #==============================================================================
  2. # ■ Scene_EventMenu
  3. #------------------------------------------------------------------------------
  4. #  处理地图画面的类。
  5. #==============================================================================

  6. class Scene_EventMenu
  7.   #--------------------------------------------------------------------------
  8.   # ● 主处理
  9.   #--------------------------------------------------------------------------
  10.   def main
  11.     # 生成活动块
  12.     @spriteset = Spriteset_Map.new
  13.     # 生成信息窗口
  14.     @message_window = Window_Message.new
  15.     # 执行过渡
  16.     Graphics.transition
  17.     if $event == nil
  18.        $event = 0
  19.     end  
  20.     if $event == 0
  21.        $event = 1
  22.        $game_temp.common_event_id = 1
  23.     else
  24.     nil
  25.     end
  26.     # 主循环
  27.     loop do
  28.       # 刷新游戏画面
  29.       Graphics.update
  30.       # 刷新输入信息
  31.       Input.update
  32.       # 刷新画面
  33.       update
  34.       # 如果画面切换的话就中断循环
  35.       if $scene != self
  36.         break
  37.       end
  38.     end
  39.     # 准备过渡
  40.     Graphics.freeze
  41.     # 释放活动块
  42.     @spriteset.dispose
  43.     # 释放信息窗口
  44.     @message_window.dispose
  45.     # 标题画面切换中的情况下
  46.     if $scene.is_a?(Scene_Title)
  47.       # 淡入淡出画面
  48.       Graphics.transition
  49.       Graphics.freeze
  50.     end
  51.   end
  52.   #--------------------------------------------------------------------------
  53.   # ● 刷新画面
  54.   #--------------------------------------------------------------------------
  55. def update
  56.   # 循环
  57.     loop do
  58.       # 按照地图、实例、主角的顺序刷新
  59.       # (本更新顺序不会在的满足事件的执行条件下成为给予角色瞬间移动
  60.       #  的机会的重要因素)
  61.       #$game_map.update
  62.       $game_system.map_interpreter.update
  63.       $game_player.update
  64.       # 系统 (计时器)、画面刷新
  65.       $game_system.update
  66.       $game_screen.update
  67.       # 如果主角在场所移动中就中断循环
  68.       unless $game_temp.player_transferring
  69.         break
  70.       end
  71.       # 执行场所移动
  72.       transfer_player
  73.       # 处理过渡中的情况下、中断循环
  74.       if $game_temp.transition_processing
  75.         break
  76.       end
  77.     end
  78.     # 刷新活动块
  79.     @spriteset.update
  80.     # 刷新信息窗口
  81.     @message_window.update
  82.   end
  83. end
复制代码

[LINE]1,#dddddd[/LINE]
    进同学说出了我忽略的问题。现在我们补充一下存档问题。首先我们看看Scene_Save中的一段脚本。
  1.   #--------------------------------------------------------------------------
  2.   # ● 确定时的处理
  3.   #--------------------------------------------------------------------------
  4.   def on_decision(filename)
  5.     # 演奏存档 SE
  6.     $game_system.se_play($data_system.save_se)
  7.     # 写入存档数据
  8.     file = File.open(filename, "wb")
  9.     write_save_data(file)
  10.     file.close
  11.     # 如果被事件调用
  12.     if $game_temp.save_calling
  13.       # 清除存档调用标志
  14.       $game_temp.save_calling = false
  15.       # 切换到地图画面
  16.       $scene = Scene_Map.new
  17.       return
  18.     end
  19.     # 切换到菜单画面
  20.     $scene = Scene_Menu.new(4)
  21.   end
复制代码

    这段脚本的意思是,当保存存档之后就返回地图然后再打开菜单。对了,没错。就是返回地图。那么我们只要让他返回那个场景就可以了。也就是返回Scene_EventMenu好了,还有读档时候的问题我等一下再补充,现在还在研究。因为发布的时候只关心菜单的部分。。。囧~~
[LINE]1,#dddddd[/LINE]
顺便贴上范例的下载地址,因为怕有同学看不懂。
[URL=http://rpg.blue/upload_program/d/玄月_Project1_113569257.rar
]点此下载[/url]

作者: 虚幻死神    时间: 2009-1-28 09:23
玄月君發教程了....看看1...看看
作者: 迅雷進    时间: 2009-1-28 13:15
前辈啊,
当选择储存进度但是又没有储存游戏而跳回出来的时候,
如图:



请前辈修改一下吧~ {/hx} {/hx}
作者: 精灵使者    时间: 2009-1-28 18:04
跳回的时候应该使用一句返回地图的指令
$scene = Scene_map.new


作者: 玄月    时间: 2009-1-28 18:37
以下引用迅雷進于2009-1-28 5:15:56的发言:

前辈啊,
当选择储存进度但是又没有储存游戏而跳回出来的时候,
如图:



请前辈修改一下吧~   

请看补充说明……
倒数第三条横线下。因为人懒所以就没有所有都修改好。其他的都按照菜单那样修改就可以了。
的确有点问题,我再发一下补充教程。
以下引用精灵使者于2009-1-28 10:04:40的发言:

跳回的时候应该使用一句返回地图的指令
$scene = Scene_map.new

返回的是用来调用事件菜单的那个Scene
作者: 精灵使者    时间: 2009-1-28 20:10
其实可以判断一下是否进入此类菜单,然后做一个条件分歧吧。
否则,事件中“调用存档画面”会出现问题的。
建议在事件菜单里设计一些开关或者公共变量来进行设置
作者: 越前リョーマ    时间: 2009-1-28 20:54
感谢提供教程……{/hx}
作者: yangff    时间: 2009-1-28 23:20
自动执行......
作者: ONEWateR    时间: 2009-1-30 10:01
那个……貌似很麻烦的说。

鼓励教程。 {/wx}

积分 += 150
作者: 玄月    时间: 2009-1-31 02:16
不麻烦…………其实只是把Scene_MAp复制一遍并把其中地图位图的刷新那行删掉再加上共用事件调用的脚本并且辅助一个变量的判定就可以了。写这么长只是为了照顾新人而已。不想看教程的看一下工程就明了了
作者: 匈魔剑    时间: 2009-1-31 02:57
哦哦,这个就是《幻剑传说》DEBUG之后的心得吧~~
抱走了,以后一定会用到的~

作者: 玄月    时间: 2009-1-31 03:32
哈啦…………我改名了改名了。然后数据库要找时间重新整理。脚本的话基本上已经完成了。
作者: asperta    时间: 2009-2-1 04:18
其实我倒是觉得用事件做菜单更麻烦,倒不如尝试直接用脚本做
作者: 玄月    时间: 2009-2-1 06:01
LS好…………= =。其实脚本是不错的。不过事件菜单对于像我这种新人来说也是很重要的东东。
作者: 3nξhα0_lim    时间: 2009-2-1 07:47
提示: 作者被禁止或删除 内容自动屏蔽
作者: 柳之一    时间: 2009-2-1 09:58
说到底仍旧是新建立场景
@spriteset = Spriteset_Map.new是用来显示地图精灵的。

和呼出默认菜单本质是一样的
作者: goahead    时间: 2009-2-1 17:31
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-1 18:57
    以下不针对某人,只是补充我在这帖子的立场而已。如有冒犯之处请提醒本人。
[LINE]1,#dddddd[/LINE]   
    我也说过可能有我还不知道的更好的方法。我这个“教程”?只是我最近发现的东东而已。我想与其闭门造车不如发布开来大家一起讨论。那么会比自己守着这么秘密的收获更大。只要这帖子大家觉得对自己有利我就觉得很开心。如果认为这个“教程”?太垃圾根本就是不入流的那我想这位大大一定是个顶级的高手,那么这帖子也对这位大大没有任何用处了。有什么批评和指教请尽量提出M(_ _)M。好吧,不说了,免得舍监骂人。
作者: 玄月    时间: 2009-2-1 19:06
以下引用goahead于2009-2-1 9:31:17的发言:

说到底只是刷新对象而已~~~~~~
Scene_Map的53行这样改:
$game_map.update if $need_update

这方法没试过,不过我觉得肯定会出错。
因为我想不出怎么呼出事件菜单。不新增一个场景的话。
作者: goahead    时间: 2009-2-2 01:22
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-2 01:41
限制了刷新,那么正常行动怎么办?
作者: 云之殇    时间: 2009-2-2 02:31
我晕倒,看来你还是事件派的坚定支持者,你这个教程偶发现偶看不懂,因为。。。。事件做菜单的想法太过夸张了,貌似比脚本还要为难{/pz},还是用脚本吧,这个貌似真的有点疯狂了{/fd}
作者: 精灵使者    时间: 2009-2-2 08:00
不过这个东西用素材做图片还真是大爱……赞一个先
作者: 赛露休斯    时间: 2009-2-2 09:26
这个事件菜单对偶这个脚本盲来说很有用,支持。。。。。。
作者: goahead    时间: 2009-2-3 00:56
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-3 01:15
你动手试试吧。纸上谈兵是没用的。 = =
作者: goahead    时间: 2009-2-3 01:23
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-3 05:12
拿我范例那个吧
作者: 纯子    时间: 2009-2-3 05:18
以下引用yangff于2009-1-28 15:20:23的发言:

自动执行......

纯引用……
作者: 玄月    时间: 2009-2-3 06:04
以下引用纯子于2009-2-2 21:18:03的发言:


以下引用yangff于2009-1-28 15:20:23的发言:

自动执行......


纯引用……

话说什么意思 = =

作者: goahead    时间: 2009-2-3 18:59
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-3 19:26
正确的答案不止一个……可是真相永远只有一个!- -+(某柯附身)
作者: goahead    时间: 2009-2-3 19:39
提示: 作者被禁止或删除 内容自动屏蔽
作者: 纯子    时间: 2009-2-3 20:12
公共事件用自动执行不就好了。。。
作者: 玄月    时间: 2009-2-3 20:14
回LS:我说NPC还是会乱动
以下引用goahead于2009-2-3 11:39:37的发言:


以下引用玄月于2009-2-3 11:26:11的发言:

正确的答案不止一个……可是真相永远只有一个!- -+(某柯附身)


哈哈,如果真相只有一个,然后还坚信自己才是真相,那就不是讨论了。

我说的真相是结果,正确的答案是手段 = =
作者: goahead    时间: 2009-2-4 23:53
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-5 06:32
    只是下手的地方不同么。可能实用性还是我那种好一点。不过因人而异吧,我的话这样做可以避免在对话中调用事件菜单。开关都省了很多,本来还想在对话脚本入手,不过弄了这个连开关判定都省了。我们思路不同可是结果是一样的。事件菜单可能是很多事件党永远的痛 - - 。
作者: goahead    时间: 2009-2-5 19:27
提示: 作者被禁止或删除 内容自动屏蔽
作者: 零℃微笑    时间: 2009-2-5 22:04
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-6 02:22
以下引用goahead于2009-2-5 11:27:27的发言:

算了我不想争什么,之前一直说只用一个变量控制刷新的方法可行,你不信我才会搞出上面的工程~~~~还有个,“避免在对话中调用事件菜单”指什么?

跟NPC对话的时候按下ESC在对话完毕之后会弹出菜单 = =,很囧的bug。
作者: goahead    时间: 2009-2-7 00:45
提示: 作者被禁止或删除 内容自动屏蔽
作者: 玄月    时间: 2009-2-7 11:00
我说我原来的工程。这个工程是我花了一点时间草草做出来的。事件菜单是旧工程的。话说用CALL_SCENE正好能避免这个bug,真是意外收获 - -+
作者: yangff    时间: 2009-2-8 05:59
  1. $角色_need_update = true
  2. class Game_Event < Game_Character
  3.   #--------------------------------------------------------------------------
  4.   # ● フレーム更新
  5.   #--------------------------------------------------------------------------
  6.   def update
  7.     return unless $角色_need_update
  8.     unless Math.hypot(@x - $game_player.x, @y - $game_player.y) > 14
  9.       super
  10.       # 自動イベントの起動判定
  11.       check_event_trigger_auto
  12.       # 並列処理が有効の場合
  13.       if @interpreter != nil
  14.         # 実行中でない場合
  15.         unless @interpreter.running?
  16.           # イベントをセットアップ
  17.           @interpreter.setup(@list, @event.id)
  18.         end
  19.         # インタプリタを更新
  20.         @interpreter.update
  21.       end
  22.     end
  23.   end
  24. end
复制代码

禁止刷新:$角色_need_update = false
要记得恢复:$角色_need_update = true
作者: azuredam    时间: 2009-8-7 10:49
提示: 作者被禁止或删除 内容自动屏蔽




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