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

Project1

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

【教程】解决调用事件菜单NPC等物还会动的问题。

 关闭 [复制链接]

Lv1.梦旅人

魔王 ⑨

梦石
0
星屑
90
在线时间
379 小时
注册时间
2006-10-16
帖子
4299

贵宾

跳转到指定楼层
1
发表于 2009-1-28 09:08:12 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
    麻烦各位老板看帖留下建议或者这个可以改进的地方。哈啦…………


    第一次写这类教程。因为也算不上教程。因为改动的地方也不多。我跟精灵说,这样的教程可能已经有了。那我也没必要再来寒暄了。可是,又想了想。其实可能本来有也很难找着了。那我还是来写着教程吧。看得顺眼的,认为对你有帮助的来签下名。觉得这篇教程没什么实际作用的鸡蛋还是什么都没所谓。尽管飞吧。寒暄就到此结束。


    首先我们知道,事件只能在地图上面调用。在菜单啊,技能啊之类的场景是不能调用的。因为地图上有关于调用事件的代码,而菜单之类的没有。
    这是个恒久的问题了。以前发布我游戏的测试版的时候,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 了。谢谢大家看我发牢骚这么久。希望这个深得猥琐教授真传教程能对你的游戏制作之路提供帮助。


    以下要补充一点东西,因为刚刚测试一遍发现了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.否则就不能打开菜单了。


这是我新建的那个场景的源代码
  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
复制代码



    进同学说出了我忽略的问题。现在我们补充一下存档问题。首先我们看看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好了,还有读档时候的问题我等一下再补充,现在还在研究。因为发布的时候只关心菜单的部分。。。囧~~


顺便贴上范例的下载地址,因为怕有同学看不懂。
[URL=http://rpg.blue/upload_program/d/玄月_Project1_113569257.rar
]点此下载[/url]
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2009-8-2
帖子
275
44
发表于 2009-8-7 10:49:40 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv2.观梦者

傻♂逼

梦石
0
星屑
374
在线时间
1606 小时
注册时间
2007-3-13
帖子
6562

烫烫烫开拓者

43
发表于 2009-2-8 05:59:29 | 只看该作者
  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
哎呀,蛋疼什么的最有爱了
回复 支持 反对

使用道具 举报

Lv1.梦旅人

魔王 ⑨

梦石
0
星屑
90
在线时间
379 小时
注册时间
2006-10-16
帖子
4299

贵宾

42
 楼主| 发表于 2009-2-7 11:00:04 | 只看该作者
我说我原来的工程。这个工程是我花了一点时间草草做出来的。事件菜单是旧工程的。话说用CALL_SCENE正好能避免这个bug,真是意外收获 - -+
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
21 小时
注册时间
2007-7-3
帖子
573
41
发表于 2009-2-7 00:45:43 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

魔王 ⑨

梦石
0
星屑
90
在线时间
379 小时
注册时间
2006-10-16
帖子
4299

贵宾

40
 楼主| 发表于 2009-2-6 02:22:12 | 只看该作者
以下引用goahead于2009-2-5 11:27:27的发言:

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

跟NPC对话的时候按下ESC在对话完毕之后会弹出菜单 = =,很囧的bug。
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2009-1-6
帖子
177
39
发表于 2009-2-5 22:04:46 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
21 小时
注册时间
2007-7-3
帖子
573
38
发表于 2009-2-5 19:27:27 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

魔王 ⑨

梦石
0
星屑
90
在线时间
379 小时
注册时间
2006-10-16
帖子
4299

贵宾

37
 楼主| 发表于 2009-2-5 06:32:32 | 只看该作者
    只是下手的地方不同么。可能实用性还是我那种好一点。不过因人而异吧,我的话这样做可以避免在对话中调用事件菜单。开关都省了很多,本来还想在对话脚本入手,不过弄了这个连开关判定都省了。我们思路不同可是结果是一样的。事件菜单可能是很多事件党永远的痛 - - 。
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
21 小时
注册时间
2007-7-3
帖子
573
36
发表于 2009-2-4 23:53:42 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2025-7-15 09:17

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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