HTML Encoder

HTML Encoder

2011年10月6日 星期四

[RMVX][RGSS腳本]多動畫疊加+地圖動畫修正

最近在研究RPG maker VX
這給我的感覺是RPG maker 2003風格再加上XP引入的強大腳本功能
雖然我很喜歡2k系列,不過自從學過寫程式以後就覺得2k系列不好用了......
而XP的畫面風格我又不喜歡,且當時我看不懂RGSS所使用的Ruby語言在幹嘛...

就這樣放棄RPG maker系列了
這幾天看到大家在實況大雄bio系列,又突然想起了這軟體的存在
這次再看Ruby語言,發現它只是個物件導向語言罷了,不難懂
學過C++ Java後真的很容易看懂它在幹嘛XDDD

anyway, 今天成功弄出了以下這個腳本


就是官方預設腳本中的地圖上動畫播放部份存在了兩個bug:
一是動畫在事件上播放時,如果主角移動,動畫會跟著移位
二是無法同時在同一個事件上播兩個以上的動畫

對於這兩個bug,大陸都有玩家寫出修正腳本
[插件脚本]地图动画显示完美修正脚本 for VX1.02
多动画叠加效果 v1.0 


不過兩個不能直接套在一起用(因為都是重寫Sprite_Base物件,只能擇一)
所以我整理了一下,把這兩個腳本的功能合在一起
就誕生這個腳本了

作法就是以"多动画叠加效果 v1.0 "為底,再把"地图动画显示完美修正脚本 for VX1.02"中將原版Sprite_Base修改的部份移進去這樣
以下腳本可自由取用


#==============================================================================
# 此腳本以"多动画叠加效果 v1.0"腳本為底修改
# 我將"地图动画显示完美修正脚本 for VX1.02"的修改部份移到此腳本中
# 讓此兩個功能可同時生效
# World 2011/01/23
#==============================================================================

#==============================================================================
# ■ Sprite_Base
#------------------------------------------------------------------------------
#  处理动画显示追加活动块的类变量。
#==============================================================================

class Sprite_Base < Sprite
  #--------------------------------------------------------------------------
  # ● 类变量
  # @@animations 用来记录动画正在播放,防止同一时间多次在同位置播放全屏动画
  # @@_reference_count 用来记录哪些素材正在被使用
  #--------------------------------------------------------------------------
  @@animations = []
  @@_reference_count = {}
  #--------------------------------------------------------------------------
  # ● done 初始化对像
  #     viewport : 视口
  #--------------------------------------------------------------------------
  def initialize(viewport = nil)
    super(viewport)
    @use_sprite = true          # 活动块使用标记
    @animation_duration = 0     # 动画剩余时间
    # 基本结构:animation, mirror, length, sprites, ox, oy ,[bitmap1, bitmap2]
    @animation_collection = []
  end
  #--------------------------------------------------------------------------
  # ● done 释放
  #--------------------------------------------------------------------------
  def dispose
    super
    return if @animation_collection == nil
    for ani in @animation_collection
      dispose_animation(ani)
    end
  end
  #--------------------------------------------------------------------------
  # ● done 刷新画面
  #--------------------------------------------------------------------------
  def update
    super
    if @animation_collection != nil
      @animation_duration -= 1
      for ani in @animation_collection
        ani[2] -= 1
        if ani[2] % 4 == 0
          update_animation(ani)
        end
      end
    end
    @@animations.clear
  end
  #--------------------------------------------------------------------------
  # ● done 动画显示中判定
  #--------------------------------------------------------------------------
  def animation?
    return @animation_collection != nil
  end
  #--------------------------------------------------------------------------
  # ● done 开始动画
  #--------------------------------------------------------------------------
  def start_animation(animation, mirror = false)
    @animation = animation
    return if @animation == nil
    @animation_mirror = mirror
    animation_length = @animation.frame_max * 4 + 1
    @animation_duration += animation_length
    animbitmap = load_animation_bitmap
    @animation_sprites = []
    if @animation.position != 3 or not @@animations.include?(animation)
      if @use_sprite
        for i in 0..15
          sprite = ::Sprite.new(viewport)
          sprite.visible = false
          @animation_sprites.push(sprite)
        end
        unless @@animations.include?(animation)
          @@animations.push(animation)
        end
      end
    end
    if @animation.position == 3
      if viewport == nil
        @animation_ox = 544 / 2
        @animation_oy = 416 / 2
      else
        @animation_ox = viewport.rect.width / 2
        @animation_oy = viewport.rect.height / 2
      end
    else
      @animation_ox = x - ox + width / 2
      @animation_oy = y - oy + height / 2
      if @animation.position == 0
        @animation_oy -= height / 2
      elsif @animation.position == 2
        @animation_oy += height / 2
      end
    end
    @animation_collection.push([@animation, @animation_mirror, animation_length,
                                @animation_sprites, @animation_ox, @animation_oy,
                                animbitmap])
  end
  #--------------------------------------------------------------------------
  # ● done 读取动画的类变量
  #--------------------------------------------------------------------------
  def load_animation_bitmap
    animation1_name = @animation.animation1_name
    animation1_hue = @animation.animation1_hue
    animation2_name = @animation.animation2_name
    animation2_hue = @animation.animation2_hue
    @animation_bitmap1 = Cache.animation(animation1_name, animation1_hue)
    @animation_bitmap2 = Cache.animation(animation2_name, animation2_hue)
    if @@_reference_count.include?(@animation_bitmap1)
      @@_reference_count[@animation_bitmap1] += 1
    else
      @@_reference_count[@animation_bitmap1] = 1
    end
    if @@_reference_count.include?(@animation_bitmap2)
      @@_reference_count[@animation_bitmap2] += 1
    else
      @@_reference_count[@animation_bitmap2] = 1
    end
    Graphics.frame_reset
    return [@animation_bitmap1, @animation_bitmap2]
  end
  #--------------------------------------------------------------------------
  # ● done 释放动画
  #--------------------------------------------------------------------------
  def dispose_animation(ani)
    if ani[6][0] != nil
      @@_reference_count[ani[6][0]] -= 1
      if @@_reference_count[ani[6][0]] == 0
        ani[6][0].dispose
      end
    end
    if ani[6][1] != nil
      @@_reference_count[ani[6][1]] -= 1
      if @@_reference_count[ani[6][1]] == 0
        ani[6][1].dispose
      end
    end
    if ani[3] != nil
      for sprite in ani[3]
        sprite.dispose
      end
      @animation_sprites = nil
      @animation = nil
    end
  end
  #--------------------------------------------------------------------------
  # ● done 刷新动画
  #--------------------------------------------------------------------------
  def update_animation(ani)
    if ani[2] > 0
      frame_index = ani[0].frame_max - (ani[2] + 3) / 4
      animation_set_sprites(ani[0].frames[frame_index], ani)
      for timing in ani[0].timings
        if timing.frame == frame_index
          animation_process_timing(timing)
        end
      end
    else
      dispose_animation(ani)
    end
  end
  #--------------------------------------------------------------------------
  # ● done 设置动画活动块
  #     frame : 帧数据 (RPG::Animation::Frame)
  #--------------------------------------------------------------------------
  def animation_set_sprites(frame, ani)
    cell_data = frame.cell_data
    for i in 0..15
      sprite = ani[3][i]
      next if sprite == nil
      pattern = cell_data[i, 0]
      if pattern == nil or pattern == -1
        sprite.visible = false
        next
      end
      if pattern < 100
        sprite.bitmap = ani[6][0]
      else
        sprite.bitmap = ani[6][1]
      end
      sprite.visible = true
      sprite.src_rect.set(pattern % 5 * 192,
        pattern % 100 / 5 * 192, 192, 192)
      #诡异之猫的地图动画显示修正(PART1) 开始
      position = ani[0].position  #ani[0] = original @animation
      if position == 3
        if self.viewport != nil
          sprite.x = self.viewport.rect.width / 2
          sprite.y = self.viewport.rect.height / 2
        else
          sprite.x = 272
          sprite.y = 208
        end
      else
        sprite.x = self.x - self.ox + self.src_rect.width / 2
        sprite.y = self.y - self.oy + self.src_rect.height / 2
        sprite.y -= self.src_rect.height / 2 if position == 0
        sprite.y += self.src_rect.height / 2 if position == 2
      end
      if @animation_mirror
        sprite.x -= cell_data[i, 1]
        sprite.y += cell_data[i, 2]
        sprite.angle = (360 - cell_data[i, 4])
        sprite.mirror = (cell_data[i, 5] == 0)
      else
        sprite.x += cell_data[i, 1]
        sprite.y += cell_data[i, 2]
        sprite.angle = cell_data[i, 4]
        sprite.mirror = (cell_data[i, 5] == 1)
      end
      sprite.z = self.z + 300 + i
      sprite.ox = 96
      sprite.oy = 96
      sprite.zoom_x = cell_data[i, 3] / 100.0
      sprite.zoom_y = cell_data[i, 3] / 100.0
      sprite.opacity = cell_data[i, 6] * self.opacity / 255.0
      sprite.blend_type = cell_data[i, 7]
    end
      #诡异之猫的地图动画显示修正(PART1) 结束

  end
  #--------------------------------------------------------------------------
  # ●  done SE 与闪烁的时机处理
  #     timing : Timing数据 (RPG::Animation::Timing)
  #--------------------------------------------------------------------------
  def animation_process_timing(timing)
    timing.se.play
    case timing.flash_scope
    when 1
      self.flash(timing.flash_color, timing.flash_duration * 4)
    when 2
      if viewport != nil
        viewport.flash(timing.flash_color, timing.flash_duration * 4)
      end
    when 3
      self.flash(nil, timing.flash_duration * 4)
    end
  end
  #--------------------------------------------------------------------------
  # ● 诡异之猫的地图动画显示修正(PART2)
  #--------------------------------------------------------------------------
  def x=(x)
    sx = x - self.x
    if sx != 0
      if @animation_sprites != nil
        for i in 0..15
          @animation_sprites[i].x += sx
        end
      end
    end
    super
  end
  def y=(y)
    sy = y - self.y
    if sy != 0
      if @animation_sprites != nil
        for i in 0..15
          @animation_sprites[i].y += sy
        end
      end
    end
    super
  end
end

6 則留言:

  1. 你好,我們工作室目前有要籌劃一款恐怖遊戲,不知道你有沒有興趣參與腳本的製作呢?

    回覆刪除
    回覆
    1. 幽兔 你好
      as you can see, 這篇是兩年前的文章 而我在這之後也沒繼續玩RMVX
      我現在也沒有程式了
      所以如果你們要找一個馬上就能開工的人的話我是幫不上忙的

      不過我自己是對寫遊戲有興趣 也許我們可以先聊一聊你們要作的遊戲內容
      這個部落格只能公開留言 所以我沒辦法給你我的其他聯絡方式

      如果方便的話 請告訴我怎麼進一步跟你們聯繫 謝謝

      刪除
    2. 請問妳都是幾點有空呢因為我們1~5都要10點半才有空
      6~日要看看有沒有事
      所以能的話可以請妳把妳可以上線的時間跟我講一下嗎感謝妳^^

      刪除
    3. Hi 我人不在台灣 台灣時間1~5晚上10點半有點難配合
      不過如果是台灣時間週六或週日的早上倒可以

      另外,我不知道你們是不是已經決定要用RMVX
      因為在你們留言後我有回去查一點RMVX的資料 ... 發現我並不是對這個很有興趣

      如果已經決定要用RMVX的話就請找別人吧 不好意思

      刪除
    4. 六日早上OK但不要太早~~~~


      刪除
  2. 妳好
    如果方便的話請今天10半來我們rc群嗎
    這樣我們比較好聊^^
    ID:26240781

    回覆刪除