目前共有3篇帖子。
【腳本】3D腳本
1樓 巨大八爪鱼 2013-2-15 16:44
#克藍娜德 CNGAMES
 
=begin
 
把下面的字符加到你的地圖名裡面
 
[W3D]  -  使用偽3D 如果你不填的話 就木有效果
 
[#XX] -  XX = 叉叉範圍是0-89之間 慣例用了我給你的偽3D看到這個是不是有違和感
 
[-X]  -  X = 這個X的範圍是0或者1 0為顯示兩面牆 1為僅顯示
 
法線正面的牆(只是個概念偽3D腫麼會有法線,也就是正面朝著你的牆)
 
如果你不寫[#XX]或者[-X]就會使用默認的
 
默認參數為:
 
[#XX] = [#45]
 
[-X] = [-1]
 
=end
 
class Game_System
 
  alias initialize_W3D initialize
 
   
  attr_reader :factor
 
  attr_reader :correct
 
 
 
  attr_reader :scroll_y
 
  attr_reader :distance
 
  attr_reader :angle
 
  attr_reader :height
 
  attr_reader :columns
 
  attr_reader :filter
 
  attr_reader :zoom
 
  attr_accessor :new_zoom
 
  attr_accessor :hidewalls
 
  attr_accessor :hide
 
  attr_accessor :new_angle
 
  attr_accessor :need_refresh
 
  attr_accessor :coord
 
  def initialize
 
    initialize_W3D
 
    @zoom = 1.00
 
    @scroll_y = 256#相機與角色的距離
 
    @height = 1    #地圖原件的高度,建議不要改 除非你做特殊效果
 
    @columns = 16   #偽3D圖塊的質量,值為8或者16。如果場景不大可以用16。
 
                   #針對縱面 8的話圖塊邊緣鋸齒比較大,流暢。16邊緣鋸齒較小,卡。
 
    @filter = 2*32 #縱向牆的高度設定(如果增加高度 不要忘了在上面加上標誌)
 
    @hidewalls = 1 #這個就是默認的雙面還是單面牆顯示的值,值為0或1。
 
    @distance = 480#焦距 玩過相機的人都知道 值不要太低,默認為480,不要低於256。
 
    #焦距值越高看到縱面的牆壁面積就越少,越低看到的牆壁面積就越多。
 
    @hide = 0#角色與原件距離的Y坐標的值,用於遮擋角色時半透明。
 
    #一個原件為32像素所以值至少為33 不然低於33 你臉貼到牆上牆都不會管你。
 
    self.angle = 45 #攝像機角度
 
    #以上屬性均可在遊戲中更改,用事件頁第三頁的腳本調用  格式為:
 
    #$game_system.(屬性) = value(值)
 
    #舉個例子:
 
    #$game_system.zoom = 1.5   #(1.5為放大150%)
 
    #或者
 
    #$game_system.columns = 8
   
    #以下為內部使用,請勿隨意更改
 
    @new_angle = false
 
    @need_refresh = false
 
    @new_zoom = false
 
    @coord = nil
 
  end
 
 
 
  #部分腳本基於Neo Mode07。
 
  def zoom=(n)
 
    if @zoom != n
 
      @new_zoom = true
 
    end
 
    @zoom = n
 
  end
 
 
 
  def refresh(x,y)
 
    @coord = [x,y]
 
  end
 
 
 
  def screen2W3D_y(y)
 
    y *= @zoom
 
    return @scroll_y + (@cd * y) / (@distance - y * @sinus)
 
  end
 
 
 
  def screen2map_y(y)
 
    return ((@distance * (@scroll_y - y) / @zoom /
 
      (@dif - y * @sinus) + @scroll_y))
 
  end
 
 
 
  def screen2zoom(y)
 
    return (y * @factor + @correct) * @zoom
 
  end
 
 
 
  def angle=(n)
 
    @angle = n
 
    @cosinus = Math.cos(Math::PI * (@angle / 180.0))
 
    @sinus = Math.sin(Math::PI * (@angle / 180.0))
 
    @cd = @cosinus * @distance
 
    @ys = @scroll_y * @sinus
 
    @dif = @ys - @cd
 
   
    z0 = @distance / (@distance + @scroll_y * @sinus)
 
    h0 = (-@distance * @scroll_y * @cosinus) /
 
      (@distance + @scroll_y * @sinus) + @scroll_y
 
    @factor = (1.0 - z0) / (@scroll_y - h0)
 
    @correct = 1.0 - @scroll_y * @factor
 
    @new_angle = true
 
  end
 
 
 
  def distance=(n)
 
    @distance = n
 
    self.angle = @angle
 
  end
 
 
 
  def height=(n)
 
    @height = n
 
    @need_refresh = true
 
  end
 
 
 
  def columns=(n)
 
    @columns = n
 
    @need_refresh = true
 
  end
 
end
 
$data_maps = load_data("Data/MapInfos.rxdata")
 
class W3DTilemap
 
  attr_reader   :autotiles
 
  attr_accessor :tileset
 
  attr_accessor :priorities
 
 
 
  def initialize(vp)
 
    @viewport = vp
 
    @horizontal = {} 
 
    @vertical = {}   
    @tileset = nil
 
    @map_data = nil
 
    @priorities = nil
 
    @bitmap = Bitmap.new(1,1)
    @sprites = []    
 
    @autotiles = []
 
    refresh
 
  end
 
 
 
  def refresh(sprites=true)
 
    @height = $game_system.height
 
    @columns = $game_system.columns
 
    @scroll_y = $game_system.scroll_y
 
    @filter = $game_system.filter
 
    @ox = -1
 
    @oy = -1
 
    if sprites
 
      w = nil
 
      @sprites.each{ |w|
 
        w.dispose}
 
      @sprites = []
 
      for i in 0...(@scroll_y / @height)
 
        @sprites[i] = Sprite.new(@viewport)
 
        @sprites[i].y = i * @height
 
      end
 
      for i in (@scroll_y / @height)...(((480-@scroll_y) / 2 + @scroll_y) /
 
                                                                      @height)
 
        @sprites[i] = Sprite.new(@viewport)
 
        @sprites[i].y = i * @height * 2 - @scroll_y
 
      end
 
    end
 
    @sprites.each {|w|
 
      w.zoom_x = $game_system.screen2zoom(w.y+1)
 
      if w.zoom_x > 1
        w.zoom_y = w.zoom_x
 
      end
 
      w.x = 320
 
    }
 
    if sprites
 
      unless @map_data.nil?
 
        refresh_bitmap
 
      end
 
    end
 
  end
 
 
 
  def terrain=(n)
 
    @terrain = n
 
  end
 
 
 
  def tileset=(bitmap)
 
    @tileset = bitmap
 
  end
 
 
 
  def ox=(n)
 
    return if @ox == n
    @ox = n
 
    dif = (@oy + @scroll_y)
    ox = n + 320
    w = nil
    i = nil
    a = nil
    z = nil
    erase = nil
 
   
    @sprites.each{ |w|
 
      w.ox = ox}
 
     
 
    @horizontal.each{ |i, a|
 
      new_y = $game_system.screen2W3D_y(i - dif)
 
      z = $game_system.screen2zoom(new_y)
 
      erase = (a[0].y - 256).between?(1,$game_system.hide)
 
      a.each{ |w|
 
        w.x = 320 + z * (w.map_x - ox)
 
        if erase and 28 >= (ox - w.map_x).abs
 
          w.opacity = 100
 
        else
 
          w.opacity = 255
 
        end
 
      }
 
    }
 
   
    @vertical.each{ |i, a|
 
      new_y = $game_system.screen2W3D_y(i - dif)
 
      z = $game_system.screen2zoom(new_y)
 
      erase = (a[0].map_y % 6 != 0)
 
      a.each{ |w|
 
        if erase and (w.map_x - ox).abs < @filter
 
          w.jump = true    
 
          w.visible = false
 
          next
 
        end
 
        w.jump = false
 
        if w.visible
 
          if w.visible = (ox*w.side >= w.map_x*w.side)
 
            w.x = 320 + z * (w.map_x - ox)
 
          end
 
        elsif w.visible = (ox*w.side >= w.map_x*w.side)
 
          w.y = new_y
 
          w.x = 320 + z * (w.map_x - ox)
 
          w.zoom_y = z
 
        end
 
      }
 
    }
 
  end
 
 
 
  def oy=(n)
 
    return if @oy == n
 
    @oy = n
 
    ox320 = @ox + 320
 
    dif = (n + @scroll_y)
 
    w = nil
    i = nil
    a = nil
    z = nil
    mz = nil
 
    new_y = nil
 
    erase = nil
 
   
    @sprites.each{ |w|
 
      w.src_rect.y = $game_system.screen2map_y(w.y+1).round + @oy
 
    }
 
   
    @horizontal.each{ |i, a|
 
      new_y = $game_system.screen2W3D_y(i - dif)
 
      z = $game_system.screen2zoom(new_y)
 
      erase = (a[0].y - 256).between?(1,$game_system.hide)
 
      a.each{ |w|
 
        w.y = new_y
 
        w.x = 320 + (z * (w.map_x - ox320))
 
        w.zoom_x = (w.zoom_y = z + 0.04)
 
        if erase and 28 >= (ox320 - w.map_x).abs
 
          w.opacity = 100
 
        else
 
          w.opacity = 255
 
        end
 
      }
 
    }
 
   
    @vertical.each{ |i, a|
    new_y = $game_system.screen2W3D_y(i - dif)
 
    z = $game_system.screen2zoom(new_y)
 
    mz = [z,1].max
 
    a.each { |w|
 
      if w.visible
 
        w.y = new_y
 
        w.x = 320 + z * (w.map_x - ox320)
 
        w.zoom_y = z
 
        w.zoom_x = mz
 
      end
 
      }
 
    }
 
  end
 
 
 
  def map_data=(data)
 
    @map_data = data
 
    refresh_bitmap
 
  end
 
 
 
  def refresh_bitmap
 
    @terrain = $game_map.terrain_tags if @terrain.nil?
 
    @horizontal.each{ |i, c|
 
      c.each{ |w|
 
        w.dispose}}
 
    @vertical.each{ |i, c|
 
      c.each{ |w|
 
        w.dispose}}
 
    @horizontal.clear
 
    @vertical.clear
 
   
    @bitmap.dispose
 
    @bitmap = Bitmap.new(@map_data.xsize*32,@map_data.ysize*32)
 
   
    rect = Rect.new(0,0,32,32)
 
    source = Rect.new(0,0,32,32)
 
    i = 0
 
    x = 0
 
    y = 0
 
    z = 0
 
    data = nil
 
    wall = nil
 
    for x in 0...@map_data.xsize
 
      for y in 0...@map_data.ysize
 
        rect.x = x*32
 
        rect.y = y*32
 
        source.x = ((@map_data[x,y,0] - 384) % 8) * 32
 
        source.y = ((@map_data[x,y,0] - 384) / 8) * 32
 
        @bitmap.stretch_blt(rect,@tileset,source)
 
        for z in 0..2
 
          data = @map_data[x,y,z]
 
          if @terrain[data] == 2 
 
            if @terrain[@map_data[[x+1,@map_data.xsize-1].min,y,z].to_i] != 2
 
              for i in 0...@columns
 
                wall = SWall.new(@viewport,@columns)
 
                wall.map_x = x * 32 + 32
 
                wall.map_y = y * 32 + (@columns-i) * 32 / @columns
 
                wall.bitmap = @tileset
 
                wall.z = wall.map_y
 
                wall.side = 1 * $game_system.hidewalls
 
                wall.set_src(@terrain, data, i)
 
                wall.ox = 32 / @columns / 2 - 1
 
                if @vertical.key?(wall.map_y)
 
                  @vertical[wall.map_y].push(wall)
 
                else
 
                  @vertical[wall.map_y] = [wall]
 
                end
 
              end
 
            end
 
            if @terrain[@map_data[[x-1,0].max,y,z].to_i] != 2
 
              for i in 0...@columns
 
                wall = SWall.new(@viewport,@columns)
 
                wall.map_x = x * 32
 
                wall.map_y = y * 32 + (@columns-i) * 32 / @columns
 
                wall.bitmap = @tileset
 
                wall.mirror = true
 
                wall.set_src(@terrain, data, i)
 
                wall.z = wall.map_y
 
                wall.side = -1 * $game_system.hidewalls
 
                wall.ox = 32 / @columns / 2
 
                if @vertical.key?(wall.map_y)
 
                  @vertical[wall.map_y].push(wall)
 
                else
 
                  @vertical[wall.map_y] = [wall]
 
                end
 
              end
 
            end
 
          end
 
          if @terrain[data] == 1 and
            (y+1 == @map_data.ysize or
 
              @map_data[x,y+1,z] != data + 8)
            wall = Wall.new(@viewport,1,@map_data)
 
            wall.map_x = x * 32 + 16
 
            wall.map_y = y * 32 + 32 + 1
 
            wall.real_y = y
 
            wall.bitmap = @tileset
 
            wall.set_src(@terrain, data)
 
            wall.ox = 15
 
            wall.z = wall.map_y
 
            if @horizontal.key?(wall.map_y)
 
              @horizontal[wall.map_y].push(wall)
 
            else
 
              @horizontal[wall.map_y] = [wall]
 
            end
 
          end
 
        end
 
      end
 
    end
 
    for i in 0...@sprites.size
 
      @sprites[i].bitmap = @bitmap
 
      @sprites[i].src_rect.set(0,i,@bitmap.width,@height)
 
      if i >= @scroll_y / @height
 
        @sprites[i].src_rect.height *= 2
 
      end
 
    end
 
  end
 
 
 
  def update
 
    if $game_system.coord
 
      x = $game_system.coord[0]
 
      y = $game_system.coord[1]
 
      source = Rect.new(0,0,32,32)
 
      rect = Rect.new(x*32,y*32,32,32)
 
      for z in 0..2
 
        if not [1,2].include?(@terrain[@map_data[x,y,z]])
 
          source.x = ((@map_data[x,y,z] - 384) % 8) * 32
 
          source.y = ((@map_data[x,y,z] - 384) / 8) * 32
 
          @bitmap.stretch_blt(rect,@tileset,source)
 
        end
 
      end
 
      $game_system.coord = nil
 
    end
 
   
    if $game_system.need_refresh
 
      $game_system.new_angle = false
 
      $game_system.need_refresh = false
 
      refresh
 
      return
 
    end
 
    if $game_system.new_zoom
 
      $game_system.new_zoom = false
 
      refresh(false)
 
      return
 
    end
 
    if $game_system.new_angle
 
      @sprites.each {|w|
 
      w.zoom_x = $game_system.screen2zoom(w.y+1)
 
        if w.zoom_x > 1
 
          w.zoom_y = w.zoom_x
 
        end
 
        w.x = 320
 
      }
 
      x = @ox
 
      y = @oy
 
      @ox += 1
 
      @oy += 1
 
      self.ox = x
 
      self.oy = y
 
      $game_system.new_angle = false
 
    end
 
  end
 
 
 
  def dispose
 
    @horizontal.each{ |i, c|
 
      c.each{ |w|
 
        w.dispose}}
 
    @vertical.each{ |i, c|
 
      c.each{ |w|
 
        w.dispose}}
 
    @sprites.each{ |w|
 
        w.dispose}
 
    @bitmap.dispose
 
  end
 
end
 
class Wall < Sprite
 
  attr_accessor :map_x
 
  attr_accessor :map_y
 
  attr_accessor :real_y
 
  attr_accessor :side
 
  attr_accessor :jump
 
  attr_accessor :height
 
  def initialize(vp,spalten,data=nil)
 
    super(vp)
 
    @data = data
 
    @spalten = spalten
 
    @jump = false
 
    @real_y = 0
 
    @map_x = 0
 
    @map_y = 0
 
    @side = 0
 
    self.x = 320
 
    self.z = 100
 
    @blick = true
 
  end
 
 
 
  def set_src(terrain,tile,i=0)
 
    height = 1
 
    while terrain[tile - height * 8].to_i == 1
 
      height += 1
 
    end
 
    self.src_rect.set(
 
            ((tile % 8) * 32) + 32 / @spalten * i,
 
            ((tile - 384) / 8 - height + 1) * 32,
 
            32 / @spalten,
 
            32 * height)
 
    self.oy = height * 32 - 1
 
    @height = height
 
  end
 
end
 
class SWall < Wall
 
  def set_src(terrain,tile,i)
 
    super
 
    self.src_rect.height -= 32
 
    self.oy -= 32
 
  end
 
end
 
class Game_Map
 
  attr_reader :W3D
 
 
 
  alias scroll_down_W3D scroll_down
 
  alias scroll_left_W3D scroll_left
 
  alias scroll_right_W3D scroll_right
 
  alias scroll_up_W3D scroll_up
 
  alias setup_W3D setup
 
 
 
  def scroll_down(distance)
 
    if $game_map.W3D
 
      @display_y += distance
 
    else
 
      scroll_down_W3D(distance)
 
    end
 
  end
 
 
 
  def scroll_left(distance)
 
    if $game_map.W3D
 
      @display_x -= distance
 
    else
 
      scroll_left_W3D(distance)
 
    end
 
  end
 
 
 
  def scroll_right(distance)
 
    if $game_map.W3D
 
      @display_x += distance
 
    else
 
      scroll_right_W3D(distance)
 
    end
 
  end
 
 
 
  def scroll_up(distance)
 
    if $game_map.W3D
 
      @display_y -= distance
 
    else
 
      scroll_up_W3D(distance)
 
    end
 
  end
 
 
 
  def name
 
    return $data_maps[@map_id].name
 
  end
 
 
 
  def setup(id)
 
    setup_W3D(id)
 
    @W3D = false
 
    for part in self.name.split("[")
 
      case part
 
      when /#(.*)\]/
 
        $game_system.angle = $1.to_i
 
      when "W3D]"
 
        @W3D = true
 
      when  /-(.*)\]/
 
        $game_system.hidewalls = $1.to_i
 
      end
 
    end
 
  end
 
end
 
class Game_Character
 
  alias screen_z_W3D screen_z
 
  def screen_z(height = 0)
 
    if $game_map.W3D
 
      if @always_on_top
 
        return $game_map.height * 32 + 10
 
      end
 
      return @real_y / 4 + 33
 
    else
 
      screen_z_W3D(height)
 
    end
 
  end
 
end
 
class Game_Player
 
  alias center_W3D center
 
  def center(x, y)
 
    if $game_map.W3D
 
      $game_map.display_x = x * 128 - CENTER_X
 
      $game_map.display_y = y * 128 - CENTER_Y
 
    else
 
      center_W3D(x, y)
 
    end
 
  end
 
end
 
class Sprite_Character
 
  alias update_W3D update
 
  def update
 
    update_W3D
 
    return unless $game_map.W3D
 
    self.y = $game_system.screen2W3D_y(self.y - $game_system.scroll_y)
 
    self.zoom_x = self.zoom_y = $game_system.screen2zoom(self.y)
 
    self.x = 320 + (self.zoom_x * (self.x - 320))
 
  end
 
end
 
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)
 
    @viewport2.z = 200
 
    @viewport3.z = 5000
 
    if $game_map.W3D
 
      @tilemap = W3DTilemap.new(@viewport1)
 
      @tilemap.terrain = $game_map.terrain_tags
 
    else
 
      @tilemap = Tilemap.new(@viewport1)
 
    end
 
    @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name)
 
    for i in 0..6
 
      autotile_name = $game_map.autotile_names[i]
 
      @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name)
 
    end
 
    @tilemap.map_data = $game_map.data
 
    @tilemap.priorities = $game_map.priorities
 
    @panorama = Plane.new(@viewport1)
 
    @panorama.z = -1000
 
    @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[i])
 
      @character_sprites.push(sprite)
 
    end
 
    @character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
 
    @weather = RPG::Weather.new(@viewport1)
 
    @picture_sprites = []
 
    for i in 1..50
 
      @picture_sprites.push(Sprite_Picture.new(@viewport2,
 
        $game_screen.pictures[i]))
 
    end
 
    @timer_sprite = Sprite_Timer.new
 
    update
 
  end
 
###########重定義update       更改遠景圖更新速度 直接複製默認的  順着箭頭往下走
 
  def update
 
    # 遠景與現在的情況有差異發生的情況下                                     ↓
 
    if @panorama_name != $game_map.panorama_name or#                         ↓
 
       @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)
 
      end
 
      Graphics.frame_reset#                                                  ↓
 
    end
 
    # 霧與現在的情況有差異的情況下                                           ↓
 
    if @fog_name != $game_map.fog_name or @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
 
    # 刷新遠景平面#                                                          ↓
 
    @panorama.ox = $game_map.display_x / 8 #這裡更改X速度                   ←
 
    @panorama.oy = $game_map.display_y * 0 #這裡更改Y速度                   ←
 
    # 刷新霧平面
 
    @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
 
    # 刷新計時器塊
 
    @timer_sprite.update
 
    # 設置畫面的色調與震動位置
 
    @viewport1.tone = $game_screen.tone
 
    @viewport1.ox = $game_screen.shake
 
    # 設置畫面的閃爍色
 
    @viewport3.color = $game_screen.flash_color
 
    # 刷新顯示端口
 
    @viewport1.update
 
    @viewport3.update
 
  end
end
2樓 巨大八爪鱼 2013-2-15 16:45
3樓 巨大八爪鱼 2014-9-13 19:45

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
 
 
©2010-2024 Arslanbar [手機版] [桌面版]
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。