じ☆ve冰风 发表于 2024-4-20 00:05:14

【脚本】显示人物立绘

自己编的一套显示人物立绘的脚本,立绘是新建的viewport,附截图与范例。
截图:
样式1:
样式2:
范例:
代码:
RUBY 代码
#============================================================================
=begin
    编制人 wolves 发布位置 rpg.blue
    显示人物立绘脚本,将下列脚本写在显示文章事件前即可显示立绘
    $text_menu=[,,
      (,type)]
    其中括号部分可以省略
    name1为 "" 则只显示右边的立绘,对话框左移;
    name2为 "" 则只显示左边的立绘,对话框右移;
    name1与name2均不为 "" 的情况下对话框居中剪短,两边一同显示立绘。
    name1为 立绘1 的文件名(picture文件夹下)
    如果觉得立绘位置不满意,可以通过left_fix1、top_fix1来修改图片位置。
    比如想要只有左面的立绘 "1.png" ,并且根据原来的位置向上移动10像素,
向左移动12像素,不缩放:
    $text_menu=[["1.png",-12,-10],[""],]#然后后面紧跟显示文章
    如果想要对图片进行缩放的话,可以修改zoom_x,zoom_y,立绘缩放是统一缩
放大小的,如果希望分别改大小的话,修改图片吧,或者参考359~365行内容
    如果想要改变成没有左右边的形式的窗口,就把type设置成1吧(type可以缺省)
=end
#============================================================================
class Game_Character_Picture
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_reader   :number                   # 图片编号
attr_reader   :name                     # 文件名
attr_reader   :origin                   # 原点
attr_reader   :x                        # X 坐标
attr_reader   :y                        # Y 坐标
attr_reader   :zoom_x                   # X 方向放大率
attr_reader   :zoom_y                   # Y 方向放大率
attr_reader   :opacity                  # 不透明度
attr_reader   :blend_type               # 合成方式
attr_reader   :tone                     # 色调
attr_reader   :angle                  # 旋转角度
#--------------------------------------------------------------------------
# ● 初始化对像
#   number : 图片编号
#--------------------------------------------------------------------------
def initialize(number)
    @number = number
    @name = ""
    @origin = 0
    @x = 0.0
    @y = 0.0
    @zoom_x = 100.0
    @zoom_y = 100.0
    @opacity = 255.0
    @blend_type = 1
    @duration = 0
    @target_x = @x
    @target_y = @y
    @target_zoom_x = @zoom_x
    @target_zoom_y = @zoom_y
    @target_opacity = @opacity
    @tone = Tone.new(0, 0, 0, 0)
    @tone_target = Tone.new(0, 0, 0, 0)
    @tone_duration = 0
    @angle = 0
    @rotate_speed = 0
end
#--------------------------------------------------------------------------
# ● 显示图片
#   name         : 文件名
#   origin       : 原点
#   x            : X 坐标
#   y            : Y 坐标
#   zoom_x       : X 方向放大率
#   zoom_y       : Y 方向放大率
#   opacity      : 不透明度
#   blend_type   : 合成方式
#--------------------------------------------------------------------------
def show(name, x, y, zoom_x, zoom_y, left_fix, top_fix)
    @name = name
    @origin = 0
    left_fix = 0if left_fix.nil?
    top_fix = 0if top_fix.nil?
    @x = left_fix + x.to_f
    @y = top_fix + y.to_f
    @zoom_x = zoom_x.to_f
    @zoom_y = zoom_y.to_f
    @opacity = 255.0
    @blend_type = 0
    @duration = 0
    @target_x = @x
    @target_y = @y
    @target_zoom_x = @zoom_x
    @target_zoom_y = @zoom_y
    @target_opacity = @opacity
    @tone = Tone.new(0, 0, 0, 0)
    @tone_target = Tone.new(0, 0, 0, 0)
    @tone_duration = 0
    @angle = 0
    @rotate_speed = 0
end
#--------------------------------------------------------------------------
# ● 开始更改色调
#   tone   : 色调
#   duration : 时间
#--------------------------------------------------------------------------
def start_tone_change(tone, duration)
    @tone_target = tone.clone
    @tone_duration = duration
    if@tone_duration == 0
      @tone = @tone_target.clone
    end
end
#--------------------------------------------------------------------------
# ● 消除图片
#--------------------------------------------------------------------------
def erase
    @name = ""
end
#--------------------------------------------------------------------------
# ● 刷新画面
#--------------------------------------------------------------------------
def update
    if@duration >= 1
      d = @duration
      @x = (@x * (d - 1) + @target_x) / d
      @y = (@y * (d - 1) + @target_y) / d
      @zoom_x = (@zoom_x * (d - 1) + @target_zoom_x) / d
      @zoom_y = (@zoom_y * (d - 1) + @target_zoom_y) / d
      @opacity = (@opacity * (d - 1) + @target_opacity) / d
      @duration -= 1
    end
    if@tone_duration >= 1
      d = @tone_duration
      @tone.red = (@tone.red * (d - 1) + @tone_target.red) / d
      @tone.green = (@tone.green * (d - 1) + @tone_target.green) / d
      @tone.blue = (@tone.blue * (d - 1) + @tone_target.blue) / d
      @tone.gray = (@tone.gray * (d - 1) + @tone_target.gray) / d
      @tone_duration -= 1
    end
    if@rotate_speed != 0
      @angle += @rotate_speed / 2.0
      while@angle < 0
      @angle += 360
      end
      @angle %= 360
    end
end
end
class Window_Message
def initialize
    super(80, 304, 480, 160)
    self.contents = Bitmap.new(width - 32, height - 32)
    self.visible = false
    self.z = 9997
    @fade_in = false
    @fade_out = false
    @contents_showing = false
    @cursor_width = 0
    self.active = false
    self.index = -1
    @indexs = if@indexs.nil?
    @changes = false
end
def refresh
    self.contents.clear
    self.contents.font.color = normal_color
    x = y = 0
    @cursor_width = 0
    # 到选择项的下一行字
    if$game_temp.choice_start == 0
      x = 8
    end
    # 有等待显示的文字的情况下
    if$game_temp.message_text != nil
      text = $game_temp.message_text
      # 限制文字处理
      begin
      last_text = text.clone
      text.gsub!(/\\\[(+)\]/){$game_variables[$1.to_i]}
      enduntil text == last_text
      text.gsub!(/\\\[(+)\]/)do
      $game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
      end
      # 为了方便、将 "\\\\" 变换为 "\000"
      text.gsub!(/\\\\/){"\000"}
      # "\\C" 变为 "\001" 将
      text.gsub!(/\\\[(+)\]/){"\001[#{$1}]"}
      # "\\G" 变为 "\002"
      text.gsub!(/\\/){"\002"}
      # c 获取 1 个字 (如果不能取得文字就循环)
      while((c = text.slice!(/./m)) != nil)
      # \\ 的情况下
      if c == "\000"
          # 还原为本来的文字
          c = "\\"
      end
      # \C 的情况下
      if c == "\001"
          # 更改文字色
          text.sub!(/\[(+)\]/, "")
          color = $1.to_i
          if color >= 0and color = 128 ? 32 : 384
            end
            @gold_window.opacity = self.opacity
            @gold_window.back_opacity = self.back_opacity
          end
          # 下面的文字
          next
      end
      # 另起一行文字的情况下
      if c == "\n"
          # 刷新选择项及光标的高
          if y >= $game_temp.choice_start
            @cursor_width = [@cursor_width, x].max
          end
          # y 加 1
          y += 1
          x = 0
          # 移动到选择项的下一行
          if y >= $game_temp.choice_start
            x = 8
          end
          # 下面的文字
          next
      end
      # 描绘文字
      unless$text_menu.nil?
          if$text_menu == 1
            unless$text_menu.empty?
            self.contents.draw_text(200 + 4 + x, 32 * y, 40, 32, c)
            # x 为要描绘文字的加法运算,文字右移200像素
            x += self.contents.text_size(c).width
            else
            self.contents.draw_text(4 + x, 32 * y, 40, 32, c)
            # x 为要描绘文字的加法运算
            x += self.contents.text_size(c).width
            end
          else
            self.contents.draw_text(4 + x, 32 * y, 40, 32, c)
            # x 为要描绘文字的加法运算
            x += self.contents.text_size(c).width
          end
      else
          self.contents.draw_text(4 + x, 32 * y, 40, 32, c)
          # x 为要描绘文字的加法运算
          x += self.contents.text_size(c).width
      end
      end
    end
    # 选择项的情况
    if$game_temp.choice_max > 0
      @item_max = $game_temp.choice_max
      self.active = true
      self.index = 0
    end
    # 输入数值的情况
    if$game_temp.num_input_variable_id > 0
      digits_max = $game_temp.num_input_digits_max
      number = $game_variables[$game_temp.num_input_variable_id]
      @input_number_window = Window_InputNumber.new(digits_max)
      @input_number_window.number = number
      @input_number_window.x = self.x + 8
      @input_number_window.y = self.y + $game_temp.num_input_start * 32
    end
end
def reset_window
    if$game_temp.in_battle
      self.y = 16
    else
      case$game_system.message_position
      when0# 上
      self.y = 16
      when1# 中
      self.y = 160
      when2# 下
      self.y = 304
      end
    end
    if$game_system.message_frame == 0
      self.opacity = 255
    else
      self.opacity = 0
    end
    self.back_opacity = 160
end
def terminate_message
    self.active = false
    self.pause = false
    self.index = -1
    self.contents.clear
    # 清除显示中标志
    @contents_showing = false
    # 呼叫信息调用
    if$game_temp.message_proc != nil
      $game_temp.message_proc.call
    end
    # 头像消失
    $game_screen.tx_pictures.erase
    $game_screen.tx_pictures.erase
    $text_menu = nil
    # 清除文章、选择项、输入数值的相关变量
    $game_temp.message_text = nil
    $game_temp.message_proc = nil
    $game_temp.choice_start = 99
    $game_temp.choice_max = 0
    $game_temp.choice_cancel_type = 0
    $game_temp.choice_proc = nil
    $game_temp.num_input_start = 99
    $game_temp.num_input_variable_id = 0
    $game_temp.num_input_digits_max = 0
    # 开放金钱窗口
    if@gold_window != nil
      @gold_window.dispose
      @gold_window = nil
    end
end
def update
    super
    # 渐变的情况下
    if@fade_in
      self.contents_opacity += 24
      if@input_number_window != nil
      @input_number_window.contents_opacity += 24
      end
      ifself.contents_opacity == 255
      @fade_in = false
      end
      return
    end
    # 输入数值的情况下
    if@input_number_window != nil
      @input_number_window.update
      # 确定
      if Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      $game_variables[$game_temp.num_input_variable_id] =
          @input_number_window.number
      $game_map.need_refresh = true
      # 释放输入数值窗口
      @input_number_window.dispose
      @input_number_window = nil
      $game_screen.tx = true
      end
      return
    end
    # 显示信息中的情况下
    if@contents_showing
      unless$text_menu.nil?
      if$text_menu == 1
          $game_screen.tx_pictures.show($text_menu, 0, self.y-100, $text_menu, $text_menu,$text_menu,$text_menu)
          $game_screen.tx_pictures.show($text_menu, 420, self.y-100, $text_menu, $text_menu,$text_menu,$text_menu)
      else
          $game_screen.tx_pictures.show($text_menu, self.x-150, self.y-100, $text_menu, $text_menu,$text_menu,$text_menu)
          $game_screen.tx_pictures.show($text_menu, self.x+self.width-40, self.y-100, $text_menu, $text_menu,$text_menu,$text_menu)
      end
      end
      # 如果不是在显示选择项中就显示暂停标志
      if$game_temp.choice_max == 0
      self.pause = true
      end
      # 取消
      if Input.trigger?(Input::B)
      if$game_temp.choice_max > 0and$game_temp.choice_cancel_type > 0
          $game_system.se_play($data_system.cancel_se)
          $game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
          terminate_message
      end
      end
      # 确定
      if Input.trigger?(Input::C)
      if$game_temp.choice_max > 0
          $game_system.se_play($data_system.decision_se)
          $game_temp.choice_proc.call(self.index)
      end
      terminate_message
      end
      return
    end
    # 在渐变以外的状态下有等待显示的信息与选择项的场合
    if@fade_out == falseand$game_temp.message_text != nil
      # 判断对话框位置
      unless$text_menu.nil?
      if$text_menu == 1
          self.x = -10
          self.width = 660
          self.contents = Bitmap.new(self.width - 32, self.height - 32)
      else
          if$text_menu.empty?
            self.x = 0
            self.width = @indexs
            self.contents = Bitmap.new(@indexs - 32, self.height - 32)
          elsif$text_menu.empty?
            self.x = @indexs
            self.width = @indexs
            self.contents = Bitmap.new(@indexs - 32, self.height - 32)
          else
            self.x=@indexs
            self.width = @indexs
            self.contents = Bitmap.new(self.width - 32, self.height - 32)
          end
      end
      else
      self.x = @indexs
      self.width = @indexs
      self.contents = Bitmap.new(@indexs - 32, self.height - 32)
      end
      @contents_showing = true
      $game_temp.message_window_showing = true
      reset_window
      refresh
      Graphics.frame_reset
      self.visible = true
      self.contents_opacity = 0
      if@input_number_window != nil
      @input_number_window.contents_opacity = 0
      end
      @fade_in = true
      return
    end
    # 没有可以显示的信息、但是窗口为可见的情况下
    ifself.visible
      @fade_out = true
      self.opacity -= 48
      ifself.opacity == 0
      self.visible = false
      @fade_out = false
      $game_temp.message_window_showing = false
      end
      return
    end
end
end
class Game_Screen
attr_accessor :tx_pictures
def initialize
    @tone = Tone.new(0, 0, 0, 0)
    @tone_target = Tone.new(0, 0, 0, 0)
    @tone_duration = 0
    @flash_color = Color.new(0, 0, 0, 0)
    @flash_duration = 0
    @shake_power = 0
    @shake_speed = 0
    @shake_duration = 0
    @shake_direction = 1
    @shake = 0
    @pictures =
    @tx_pictures=[]
    for i in1..100
      @pictures.push(Game_Picture.new(i))
    end
    for i in0..1
      @tx_pictures.push(Game_Character_Picture.new(i))
    end
    @weather_type = 0
    @weather_max = 0.0
    @weather_type_target = 0
    @weather_max_target = 0.0
    @weather_duration = 0
end
def update
    if@tone_duration >= 1
      d = @tone_duration
      @tone.red = (@tone.red * (d - 1) + @tone_target.red) / d
      @tone.green = (@tone.green * (d - 1) + @tone_target.green) / d
      @tone.blue = (@tone.blue * (d - 1) + @tone_target.blue) / d
      @tone.gray = (@tone.gray * (d - 1) + @tone_target.gray) / d
      @tone_duration -= 1
    end
    if@flash_duration >= 1
      d = @flash_duration
      @flash_color.alpha = @flash_color.alpha * (d - 1) / d
      @flash_duration -= 1
    end
    if@shake_duration >= 1or@shake != 0
      delta = (@shake_power * @shake_speed * @shake_direction) / 10.0
      if@shake_duration@shake_power * 2
      @shake_direction = -1
      end
      if@shake < - @shake_power * 2
      @shake_direction = 1
      end
      if@shake_duration >= 1
      @shake_duration -= 1
      end
    end
    if@weather_duration >= 1
      d = @weather_duration
      @weather_max = (@weather_max * (d - 1) + @weather_max_target) / d
      @weather_duration -= 1
      if@weather_duration == 0
      @weather_type = @weather_type_target
      end
    end
    if$game_temp.in_battle
      for i in51..100
      @pictures.update
      end
    else
      for i in1..50
      @pictures.update
      end
    end
    for i in0..1
      @tx_pictures.update
    end
end
end
#==============================================================================
# ■ Spriteset_Map
#------------------------------------------------------------------------------
#  处理地图画面活动块和元件的类。本类在
# Scene_Map 类的内部使用。
#==============================================================================

class Spriteset_Map
#--------------------------------------------------------------------------
# ● 初始化对像
#--------------------------------------------------------------------------
def initialize
    # 生成显示端口
    @viewport1 = Viewport.new(0, 0, 640, 480)
    @viewport2 = Viewport.new(0, 0, 640, 480)
    @viewport3 = Viewport.new(0, 0, 640, 480)
    @viewport4 = Viewport.new(0, 0, 640, 480)
    @viewport2.z = 200
    @viewport3.z = 5000
    @viewport4.z = 9998
    # 生成元件地图
    @tilemap = Tilemap.new(@viewport1)
    @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name)
    for i in0..6
      autotile_name = $game_map.autotile_names
      @tilemap.autotiles = RPG::Cache.autotile(autotile_name)
    end
    @tilemap.map_data = $game_map.data
    @tilemap.priorities = $game_map.priorities
    # 生成远景平面
    @panorama = Plane.new(@viewport1)
    @panorama.z = -1000
    # 生成覆盖远景平面
#    if DKRM::FUNC_TWOMAP
#      @panoramaz = Plane.new(@viewport1)
#      @panoramaz.z = 2999
#    end
    # 生成雾平面
    @fog = Plane.new(@viewport1)
    @fog.z = 3000
    # 生成角色活动块
    @character_sprites = []
    for i in$game_map.events.keys.sort
      sprite = Sprite_Character.new(@viewport1, $game_map.events)
      @character_sprites.push(sprite)
    end
    @character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
    # 生成天气
    @weather = RPG::Weather.new(@viewport1)
    # 生成图片
    @picture_sprites = []
    for i in1..50
      @picture_sprites.push(Sprite_Picture.new(@viewport2,
      $game_screen.pictures))
    end
    @tx_picture_sprites = []
    for i in0..1
      @tx_picture_sprites.push(Sprite_Picture.new(@viewport4,
      $game_screen.tx_pictures))
    end
    # 生成计时器块
    @timer_sprite = Sprite_Timer.new
    # 刷新画面
    update
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
    # 释放元件地图
    @tilemap.tileset.dispose
    for i in0..6
      @tilemap.autotiles.dispose
    end
    @tilemap.dispose
    # 释放远景平面
    @panorama.dispose
    # 释放覆盖远景平面
#    if DKRM::FUNC_TWOMAP
#      @panoramaz.dispose
#    end
    # 释放雾平面
    @fog.dispose
    # 释放角色活动块
    for sprite in@character_sprites
      sprite.dispose
    end
    # 释放天候
    @weather.dispose
    # 释放图片
    for sprite in@picture_sprites
      sprite.dispose
    end
    for sprite in@tx_picture_sprites
      sprite.dispose
    end
    # 释放计时器块
    @timer_sprite.dispose
    # 释放显示端口
    @viewport1.dispose
    @viewport2.dispose
    @viewport3.dispose
    @viewport4.dispose
end
#--------------------------------------------------------------------------
# ● 刷新画面
#--------------------------------------------------------------------------
def update
    # 远景与现在的情况有差异发情况下
    if@panorama_name != $game_map.panorama_nameor
       @panorama_hue != $game_map.panorama_hue
      @panorama_name = $game_map.panorama_name
      @panorama_hue = $game_map.panorama_hue
      if@panorama.bitmap != nil
      @panorama.bitmap.dispose
      @panorama.bitmap = nil
      end
      if@panorama_name != ""
      @panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue)
#      if DKRM::FUNC_TWOMAP and\
#          FileTest.exist?("Graphics/Panoramas/" + @panorama_name + "_2.png")
#          @panoramaz.bitmap = RPG::Cache.panorama(@panorama_name + "_2"\
#          ,@panorama_hue)
#      end
      end
      Graphics.frame_reset
    end
    # 雾与现在的情况有差异的情况下
    if@fog_name != $game_map.fog_nameor@fog_hue != $game_map.fog_hue
      @fog_name = $game_map.fog_name
      @fog_hue = $game_map.fog_hue
      if@fog.bitmap != nil
      @fog.bitmap.dispose
      @fog.bitmap = nil
      end
      if@fog_name != ""
      @fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue)
      end
      Graphics.frame_reset
    end
    # 刷新元件地图
    @tilemap.ox = $game_map.display_x / 4
    @tilemap.oy = $game_map.display_y / 4
    @tilemap.update
    # 刷新远景与覆盖远景平面
    m = 8
#    if DKRM::FUNC_TWOMAP
#      m = 4
#      @panoramaz.ox = $game_map.display_x / 4
#      @panoramaz.oy = $game_map.display_y / 4
#    end
    @panorama.ox = $game_map.display_x / m
    @panorama.oy = $game_map.display_y / m
    # 刷新雾平面
    @fog.zoom_x = $game_map.fog_zoom / 100.0
    @fog.zoom_y = $game_map.fog_zoom / 100.0
    @fog.opacity = $game_map.fog_opacity
    @fog.blend_type = $game_map.fog_blend_type
    @fog.ox = $game_map.display_x / 4 + $game_map.fog_ox
    @fog.oy = $game_map.display_y / 4 + $game_map.fog_oy
    @fog.tone = $game_map.fog_tone
    # 刷新角色活动块
    for sprite in@character_sprites
      sprite.update
    end
    # 刷新天候图形
    @weather.type = $game_screen.weather_type
    @weather.max = $game_screen.weather_max
    @weather.ox = $game_map.display_x / 4
    @weather.oy = $game_map.display_y / 4
    @weather.update
    # 刷新图片
    for sprite in@picture_sprites
      sprite.update
    end
    for sprite in@tx_picture_sprites
      sprite.update
    end
    # 刷新计时器块
    @timer_sprite.update
    # 设置画面的色调与震动位置
    @viewport1.tone = $game_screen.tone
    @viewport1.ox = $game_screen.shake
    # 设置画面的闪烁色
    @viewport3.color = $game_screen.flash_color
    # 刷新显示端口
    @viewport1.update
    @viewport3.update
    @viewport4.update
end
end

            本帖来自P1论坛作者wolves,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=376616若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页: [1]
查看完整版本: 【脚本】显示人物立绘