#克藍娜德 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