查看: 1764|回复: 4

[已经解决] 一个无脑的问题,余烬之中的这个脚本怎么知道窗口编号?

[复制链接]
梦石
0
星屑
130
在线时间
124 小时
注册时间
2015-12-20
回帖
26
发表于 2016-9-9 19:25:41 | 显示全部楼层 |阅读模式

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

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

×
什么叫"新建窗口的时候生成一个编号 然后返回给【新增文本窗口】"?难道是执行那个方法,然后直接return编号?
[pre lang="ruby"]# 如何显示一个显示指定文字的窗口?要求文字能够在游戏中修改。

# 这个问题有点诡异啊:到底是在哪里显示呢?菜单?标题?存档界面?GameOver?……
# (再唧唧歪歪就把你送给楼主做女仆)
# 咳咳,我们假设这是要显示在地图上的 很显然 我们至少需要了解:
#  位置(x, y)
#  文本(text)
# 鉴于默认窗口太丑,我们需要一个作为补充的图片背景功能:
#  背景(background)
# 允许设定的项 除了文本外 还有窗口的不透明度(opacity)
# 窗口的大小就自适应文字吧 有背景图的话就固定为背景图的大小

# 我们的设想中 可以通过事件脚本来更改某窗口的文字
# 还可以新建窗口 用两个窗口来显示文字 甚至三个四个好多个

# 因为各项参数都用事件脚本 所以我们不需要用模块进行设置了好可惜

# 一般而言 事件脚本调用的环境是Game_Interpreter内部 不要问我环境是什么
# 反正保护环境 人人有责(我在说什么)
#==============================================================================
# ** Game_Interpreter
#==============================================================================
class Game_Interpreter
  def 新增文本窗口(文本, 横坐标 = 0, 纵坐标 = 0, 背景图片 = "", 不透明度 = 255)
    # 各种默认值就在上面设置完成 不需要玩家如何如何地设置
    # 乖乖调用【新增文本窗口(...)】就可以了
    SceneManager.scene.新增文本窗口(文本, 横坐标, 纵坐标, 背景图片, 不透明度)
    # SceneManager.scene获取当前场景 一般是地图场景
    # 后面这个方法 我们还没有在地图场景里面实现
    # 但是不要紧了 反正后面会实现的
  end
  def 更改窗口文本(窗口编号, 文本 = "")
    # 我怎么知道窗口编号?
    # 很简单 新建窗口的时候生成一个编号 然后返回给【新增文本窗口】
    # 让用户截取这个编号并保存 那不关我们的事
    SceneManager.scene.更改窗口文本(窗口编号, 文本)
  end
  def 更改窗口位置(窗口编号, 横坐标 = 0, 纵坐标 = 0)
    SceneManager.scene.更改窗口位置(窗口编号, 横坐标, 纵坐标)
  end
  def 更改窗口背景图片(窗口编号, 背景图片 = "")
    SceneManager.scene.更改窗口背景图片(窗口编号, 背景图片)
  end
  def 更改窗口不透明度(窗口编号, 不透明度 = 255)
    SceneManager.scene.更改窗口不透明度(窗口编号, 不透明度)
  end
  def 获取窗口信息(窗口编号)
    # 应该返回一个数组:[文本, 背景图片, 不透明度]
    SceneManager.scene.获取窗口信息(窗口编号)
  end
  def 删除窗口(窗口编号)
    SceneManager.scene.删除窗口(窗口编号)
  end
  def 暂时关闭窗口(窗口编号)
    SceneManager.scene.暂时关闭窗口(窗口编号)
  end
  def 暂时打开窗口(窗口编号)
    SceneManager.scene.暂时打开窗口(窗口编号)
  end
end

# 但是我们的窗口连影子都没有
# 开工了伙计们
class Window_ShowTextOnMap < Window_Base # 果然还是继承Base吧
  def initialize(text, x, y, back, opa)
    @text, @back, @opa = text, back, opa
    if @back == ""
      super(x, y, *get_width_and_height) #不使用背景图片 自适应文字
      self.opacity = @opa
    else
      pic = Cache.picture(@back) # Cache.picture访问的是Graphics/Picture文件夹
      super(x, y, pic.width, pic.height) # 使用背景图片 根据图片来
      self.back_opacity = 0
      self.contents_opacity = @opa
    end
    # get_width_and_height是一个不存在的方法 我们将要实现它
    # 使它返回文本合适的宽与高(以数组的形式)
    # 前面加一个*号 目的是将数组展开 因为super呼叫父类方法 在这里要四个参数
    refresh
    # 描绘文字
  end

  # 获取合适的宽与高 允许使用控制符 比如\I[3] \n \V[6]
  # 原理: 新建一个临时窗口 画一遍 观测绘制的范围 就知道合适的宽与高了
  def get_width_and_height
    tmp = Window_Base.new(Graphics.width, 0, Graphics.width, 1)
    # 新建临时窗口
    tmp.reset_font_settings
    # 重置字体设置
    width = 0
    # 记录宽度
    pos = {x: 0, y: 0, height: tmp.calc_line_height(@text)}
    # 当前描绘的位置
    @text.each_line do |s| # 逐行描绘
      # s.gsub!(/[\n]/){""} # 去除尾部的换行符 理论上可以用chomp!代替
      s.chomp! # 我想我们还是用更拉风的chomp!吧
      tmp.process_character(s.slice!(0, 1), s, pos) until s.empty? # 逐字描绘
      width = [pos[:x], width].max # 获取单行的宽度 记录最大值
      pos[:x] = 0 # 换行
      pos[:y] += pos[:height] # 换行
      pos[:height] = tmp.calc_line_height s #确定合适高度
      # 循环描绘下一行
    end
    # 没有手动对tmp进行dispose 因为它在窗口外 看不到 而且tmp作用域要消失了
    #  很快就会被GC弄死 这里不需要理解
    [width + standard_padding * 2, pos[:y] + standard_padding * 2] # 返回宽高
  end

  # 进行实际的描绘
  def refresh
    contents.clear
    pic = Cache.picture(@back)
    contents.blt(0, 0, pic, Rect.new(0, 0, pic.width, pic.height))
    draw_text_ex(0, 0, @text)
  end

  # 改变文字
  def set_text(text)
    @text = text
    refresh
  end

  # 位置
  def set_pos(x, y)
    self.x, self.y = x, y
  end

  # 背景图片
  def set_back(back)
    return if @back == back
    @back = back
    if @back == ""
      self.move(self.x, self.y, *get_width_and_height)
      self.opacity = @opa
    else
      pic = Cache.picture(@back)
      self.move(self.x, self.y, pic.width, pic.height)
      self.back_opacity = 0
      self.contents_opacity = @opa
    end
    refresh
  end

  # 不透明度
  def set_opa(opa)
    @opa = opa
    if @back == ""
      self.opacity = @opa
    else
      self.contents_opacity = @opa
    end
  end

  # 获取信息
  def get_info
    [@text, @back, @opa]
  end
end

# 好无聊 累死了 不想写了 就这样吧
# ………………
# 为了不做楼主女仆 我还是继续吧

# 我们已经完成了一个【入口】 可以接受事件脚本信息 但是还没有人来处理
# 我们已经完成了一个【窗口】 可以在地图上显示文本 但是还没有人来管理
# 所有的事实都指向一个结果 真相只有一个!

class Scene_Map
  # 首先 在开始的时候地图场景会建立一系列窗口
  # 我们把我们的窗口混进去一起建立…………不需要一次性建好 放个名单就行
  # 在方法create_all_windows中
  alias :我要往你里面塞一点东西哦_create_all_windows君 :create_all_windows
  def create_all_windows
    我要往你里面塞一点东西哦_create_all_windows君
    我要塞的东西之一
  end

  def 我要塞的东西之一
    @显示文本的窗口们 = []
  end

  def 新增文本窗口(text, x, y, back, opa)
    @显示文本的窗口们.push(Window_ShowTextOnMap.new(text, x, y, back, opa))
    @显示文本的窗口们.size - 1 # 这就是返回的窗口编号啦
  end

  def 更改窗口文本(id, text)
    @显示文本的窗口们[id].set_text(text)
  end

  def 更改窗口位置(id, x, y)
    @显示文本的窗口们[id].set_pos(x, y)
  end

  def 更改窗口背景图片(id, back)
    @显示文本的窗口们[id].set_back(back)
  end

  def 更改窗口不透明度(id, opa = 255)
    @显示文本的窗口们[id].set_opa(opa)
  end

  def 获取窗口信息(id)
    @显示文本的窗口们[id].get_info
  end

  def 删除窗口(id)
    @显示文本的窗口们[id].dispose
  end

  def 暂时关闭窗口(id)
    @显示文本的窗口们[id].close if @显示文本的窗口们[id].open?
  end

  def 暂时打开窗口(id)
    @显示文本的窗口们[id].open if @显示文本的窗口们[id].close?
  end

  # 很好 虽然这种重复冗余令人难以置信 但是完成了不是吗?元编程去死吧!

  # 等等 我们是不是忘了什么?

  # 更新!update!释放!dispose!
  alias :我也要往你里面塞一点东西哦_update_all_windows君 :update_all_windows
  def update_all_windows
    我也要往你里面塞一点东西哦_update_all_windows君
    我要塞的东西之二
  end

  def 我要塞的东西之二
    @显示文本的窗口们.each{|x| x.update unless x.disposed?}
  end

  alias :我还要往你里面塞一点东西哦_dispose_all_windows君 :dispose_all_windows
  def dispose_all_windows
    我还要往你里面塞一点东西哦_dispose_all_windows君
    我要塞的东西之三
  end

  def 我要塞的东西之三
    @显示文本的窗口们.each{|x| x.dispose unless x.disposed?}
  end
end
# 完美!

# 照例装逼化

__END__

#==============================================================================
# ** Game_Interpreter
#==============================================================================
class Game_Interpreter
  def new_text_window(text, x = 0, y = 0, back = "", opa = 255)
    SceneManager.scene.new_text_window(text, x, y, back, opa)
  end
  def delete_text_window(id)
    SceneManager.scene.delete_text_window(id)
  end
  def close_text_window(id)
    SceneManager.scene.close_text_window(id)
  end
  def open_text_window(id)
    SceneManager.scene.open_text_window(id)
  end
  def text_window_set_text(id, text = "")
    SceneManager.scene.text_window_set_text(id, text)
  end
  def text_window_set_pos(id, x = 0, y = 0)
    SceneManager.scene.text_window_set_pos(id, x, y)
  end
  def text_window_set_back(id, back = "")
    SceneManager.scene.text_window_set_back(id, back)
  end
  def text_window_set_opa(id, opa = 255)
    SceneManager.scene.text_window_set_opa(id, opa)
  end
  def text_window_get_info(id)
    SceneManager.scene.text_window_get_info(id)
  end
end
#==============================================================================
# ** Window_ShowTextOnMap
#==============================================================================
class Window_ShowTextOnMap < Window_Base
  def initialize(text, x, y, back, opa)
    @text, @back, @opa = text, back, opa
    if @back.empty?
      super(x, y, *get_width_and_height)
      self.opacity = @opa
    else
      pic = Cache.picture(@back)
      super(x, y, pic.width, pic.height)
      self.back_opacity = 0
      self.contents_opacity = @opa
    end
    refresh
  end

  def get_width_and_height
    tmp = Window_Base.new(Graphics.width, 0, Graphics.width, 1)
    tmp.reset_font_settings
    width = 0
    pos = {x: 0, y: 0, height: tmp.calc_line_height(@text)}
    @text.each_line do |s|
      s.chomp!
      tmp.process_character(s.slice!(0, 1), s, pos) until s.empty?
      width = [pos[:x], width].max
      pos[:x] = 0
      pos[:y] += pos[:height]
      pos[:height] = tmp.calc_line_height s
    end
    [width + standard_padding * 2, pos[:y] + standard_padding * 2]
  end

  def refresh
    contents.clear
    pic = Cache.picture(@back)
    contents.blt(0, 0, pic, Rect.new(0, 0, pic.width, pic.height))
    draw_text_ex(0, 0, @text)
  end

  def set_text(text)
    @text = text
    refresh
  end

  def set_pos(x, y)
    self.x, self.y = x, y
  end

  def set_back(back)
    return if @back == back
    @back = back
    if @back.empty?
      self.move(self.x, self.y, *get_width_and_height)
      self.opacity = @opa
    else
      pic = Cache.picture(@back)
      self.move(self.x, self.y, pic.width, pic.height)
      self.back_opacity = 0
      self.contents_opacity = @opa
    end
    refresh
  end

  def set_opa(opa)
    @opa = opa
    if @back == ""
      self.opacity = @opa
    else
      self.contents_opacity = @opa
    end
  end

  def get_info
    [@text, @back, @opa]
  end
end
#==============================================================================
# ** Scene_Map
#==============================================================================
class Scene_Map
  alias :text_window_create_all_windows :create_all_windows
  def create_all_windows
    text_window_create_all_windows
    create_text_windows
  end

  def create_text_windows
    @text_windows = []
  end

  alias :text_window_update_all_windows :update_all_windows
  def update_all_windows
    text_window_update_all_windows
    update_text_windows
  end

  def update_text_windows
    @text_windows.each{|x| x.update unless x.disposed?}
  end

  alias :text_window_dispose_all_windows :dispose_all_windows
  def dispose_all_windows
    text_window_dispose_all_windows
    dispose_text_windows
  end

  def dispose_text_windows
    @text_windows.each{|x| x.dispose unless x.disposed?}
  end

  def new_text_window(*args)
    @text_windows.push Window_ShowTextOnMap.new(*args)
    @text_windows.size - 1
  end

  def delete_text_window(id)
    @text_windows[id].dispose
  end

  def close_text_window(id)
    @text_windows[id].close if @text_windows[id].open?
  end

  def open_text_window(id)
    @text_windows[id].open if @text_windows[id].close?
  end

  def text_window_set_text(id, text)
    @text_windows[id].set_text(text)
  end

  def text_window_set_pos(id, x, y)
    @text_windows[id].set_pos(x, y)
  end

  def text_window_set_back(id, back)
    @text_windows[id].set_back(back)
  end

  def text_window_set_opa(id, opa = 255)
    @text_windows[id].set_opa(opa)
  end

  def text_window_get_info(id)
    @text_windows[id].get_info
  end
end
[/pre]

梦石
1
星屑
23241
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2016-9-9 20:09:31 | 显示全部楼层
执行 新增文本窗口 这个方法的时候返回值是该窗口的一个编号(ID、句柄……),用于在其他操作窗口的方法中调用这个窗口

点评

那我怎么知道编号到底是多少...  发表于 2016-9-10 16:14
回复

使用道具 举报

梦石
1
星屑
23241
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2016-9-10 17:20:22 | 显示全部楼层
你创建窗口的时候的返回值就是一个编号,你可以直接
  1. $game_variables[1] = 新增文本窗口(参数)
复制代码

1 号变量就是窗口的变好了

点评

哦...  发表于 2016-9-11 12:47

评分

参与人数 1星屑 +250 梦石 +1 收起 理由
RaidenInfinity + 250 + 1 楼主认可的解答

查看全部评分

回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部