Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- =begin
- ===============================================================================
- XPA Tilemap Version 0.11b
- by KK20 03 Nov 2014
- _______________________________________________________________________________
- [ Version History]
- Ver. Date Notes
- ----- ----------- ----------------------------------------------------
- 0.11b ... 03 Nov 2014 ... Bug fixes:
- - Table did not take in parameters upon initialize
- - Centering of maps now shrinks Viewport sizes
- - Fixed Tilemap#oy= logic
- 0.1b ... 02 Nov 2014 ... Initial release
- _______________________________________________________________________________
- [ Introduction ]
- In light of recent discoveries regarding the usage of RGSS3 in RPG Maker XP
- games, many users were left with a dilemma in choosing which Tilemap rewrite
- to use due to the vast differences between RGSS1's and RGSS3's Tilemap classes
- that would cause complications in this transition. I aimed to find the best
- Tilemap rewrite and decided that I would have to make my own. Like every other
- Tilemap rewrite before it, this implementation is in no ways perfect, boasting
- PROs and CONs.
- This script is intended to be used for RPG Maker XP games using the RGSS3
- library (unofficially coined RPG Maker XP Ace); however, it is entirely
- compatible with RPG Maker XP games in the RGSS1 library.
- _______________________________________________________________________________
- [ License ]
- This work is protected by the following license:
- http://creativecommons.org/licenses/by-nc-sa/3.0/
- *******************************************************************************
- You are free:
- to Share - to copy, distribute and transmit the work
- to Remix - to adapt the work
- Under the following conditions:
- Attribution:
- You must attribute the work in the manner specified by the author or licensor,
- but not in any way that suggests that they endorse you or your use of the work.
- Noncommercial:
- You may not use this work for commercial purposes.
- Share alike:
- If you alter, transform, or build upon this work, you may distribute the
- resulting work only under the same or similar license to this one.
- - For any reuse or distribution, you must make clear to others the license
- terms of this work. The best way to do this is with a link to this web page.
- - Any of the above conditions can be waived if you get permission from the
- copyright holder.
- - Nothing in this license impairs or restricts the author's moral rights.
- *******************************************************************************
- [ Instructions ]
- - Place this script below the default scripts but above Main.
- - Move 'XPATilemap.dll' into your project folder (same directory as 'Game.exe')
- - Configure values at the start of the script
- More detailed instructions can be found in the PDF that came with this script.
- _______________________________________________________________________________
- [ Features ]
- About the script:
- - XP and XPA (RGSS1 and RGSS3) compatible
- - Define your own custom resolution
- - Maps that are smaller than the game resolution are automatically centered
- - Drawing methods written in C-language, which has faster pixel-by-pixel
- operations than Ruby
- Add-ons:
- - Customize frame rate animation and define unique patterns for your autotiles
- - Remove unnecessary priority layers to boost frames-per-second (FPS)
- - Extend the default RPG::Weather class to fit larger screens, or not
- - more to add later...
- _______________________________________________________________________________
- [ Compatibility ]
- Unknown at this time...
- _______________________________________________________________________________
- [ Credits ]
- KK20 - Author of this script and DLL
- Zexion - Tester and morale support
- ForeverZer0 - Reusing code from his Custom Resolution script, found here:
- http://forum.chaos-project.com/index.php/topic,7814.0.html
- LiTTleDRAgo - Reusing code from his edits to Custom Resolution
- _______________________________________________________________________________
- [ Contact ]
- To contact the author of this script, please visit
- http://forum.chaos-project.com/index.php
- or send an email to
- tscrane20@gmail.com
- ===============================================================================
- =end
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # B E G I N C O N F I G U R A T I O N
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- #------------------------------------------------------------------------------
- # The game window's screen resolution. RPG Maker XP's default is [640, 480].
- # Do note that a larger resolution is prone to sprite lag.
- #------------------------------------------------------------------------------
- SCREEN_RESOLUTION = [740,510]
- #------------------------------------------------------------------------------
- # Save modified resolution to a file, change to false to disable
- # To modify resolution, use $resolution.resize_screen(width,height)
- #------------------------------------------------------------------------------
- SAVE_RESOLUTION_TO_FILE = "Resolution.rxdata"
- #------------------------------------------------------------------------------
- # The largest level of priority your game uses. This value should be between
- # 1 and 5. If using a large resolution, lowering the number of priority layers
- # will help in reducing the lag.
- #------------------------------------------------------------------------------
- MAX_PRIORITY_LAYERS = 5
- #------------------------------------------------------------------------------
- # If using a larger resolution than 640x480, the default weather effects will
- # look sparse as there are fewer sprites to cover a wider area. Setting this to
- # TRUE will increase the number of sprites proportionally. This will create
- # more lag as a result.
- #------------------------------------------------------------------------------
- WEATHER_ADJUSTMENT = false
- #------------------------------------------------------------------------------
- # Prevents the player from using ALT + ENTER to go into Fullscreen Mode. Note
- # that this change applies to all applications on the player's computer.
- #------------------------------------------------------------------------------
- DISABLE_ALT_ENTER = true
- #------------------------------------------------------------------------------
- # Set the animation frame rate for autotiles. By default, all autotiles will
- # update on the 16th frame. You can change that by providing an array of
- # numbers that represent how many frames that particular frame on animation
- # will be visible for.
- #------------------------------------------------------------------------------
- def autotile_framerate(filename)
- case filename
- when '009-G2_Water01' then return [8,8,8,8]
- when '001-G_Water01' then return [20,20,20,20]
- when '024-Ocean01' then return [32,16,32,16]
- else
- # Generates array of [16, 16, ...] based on autotile width
- # (or nil if not animating autotile)
- w = RPG::Cache.autotile(filename).width
- h = RPG::Cache.autotile(filename).height
- if (h == 32 && w / 32 == 1) || (h == 192 && w / 256 == 1)
- return nil
- else
- return h == 32 ? Array.new(w/32){|i| 16} : Array.new(w/256){|i| 16}
- end
- end
- end
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # E N D C O N F I G U R A T I O N
- #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- if DISABLE_ALT_ENTER
- # Disable ALT+Enter
- reghotkey = Win32API.new('user32', 'RegisterHotKey', 'LIII', 'I')
- reghotkey.call(0, 1, 1, 0x0D)
- end
- XPACE = RUBY_VERSION == "1.9.2"
- #==============================================================================
- # ** Resolution
- #==============================================================================
- class Resolution
- SAVEDATA = SAVE_RESOLUTION_TO_FILE
- attr_reader :version, :window
- define_method(:width) { @width ||= SCREEN_RESOLUTION[0] }
- define_method(:height) { @height ||= SCREEN_RESOLUTION[1] }
- define_method(:maxsize) { [@metrics.call(0), @metrics.call(1)] }
- define_method(:fullscreen?){ [@width,@height] == maxsize }
- define_method(:fullscreen) { fullscreen?||resize_screen(*maxsize) }
- define_method(:window) { fullscreen?&&(s=@old_size)&&resize_screen(*s) }
- def initialize
- # Define version.
- @version = 1.12
- # Set instance variables for calling basic Win32 functions.
- ini = Win32API.new('kernel32', 'GetPrivateProfileString','PPPPLP', 'L')
- ini.call('Game', 'Title', '', (title = "\0" * 256), 256, '.\\Game.ini')
- findwindow = Win32API.new('user32','FindWindow','PP','I')
- @set_window_long = Win32API.new('user32', 'SetWindowLong', 'LIL', 'L')
- @set_window_pos = Win32API.new('user32', 'SetWindowPos', 'LLIIIII', 'I')
- @metrics = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
- @window = findwindow.call('RGSS Player', title.delete!("\0"))
- # Apply resolution change.
- load_setting
- end
- #--------------------------------------------------------------------------
- def resize_screen(w,h)
- @old_size = [width,height] unless [width,height] == (s = maxsize)
- @width, @height = w, h
- $game_map.refresh_map_edge if $game_map
- $scene = $scene.class.new if $scene
- $game_player.center($game_player.x,$game_player.y) if $game_player
- if (save = SAVEDATA) && (File.exist?(save) or [w,h] != SCREEN_RESOLUTION)
- Marshal.dump([w,h,@old_size], (file=File.open(save,"wb"))) && file.close
- end
- Graphics.resize_screen(w,h) if Graphics.respond_to?(:resize_screen)
- @set_window_long.call(@window, -16, s == [w,h] ? 0x14000000 : 0x14CA0000)
- @set_window_pos.call(@window,0,(s[0]-w)/2,(s[1]-h)/2, w, h, 0)
- end
- #--------------------------------------------------------------------------
- def load_setting
- if (load = SAVEDATA) && File.exist?(load)
- (res = Marshal.load((file = File.open(load, "rb")))) && file.close
- (@width, @height = res.at(2)) if res.at(2)
- (resize_screen(res.at(0), res.at(1)))
- else
- resize_screen(width,height)
- end
- end
- #--------------------------------------------------------------------------
- end
- #==============================================================================
- # ** RPG::Cache
- #==============================================================================
- module RPG::Cache
- AUTO_INDEX = [[
- [27,28,33,34], [ 5,28,33,34], [27, 6,33,34], [ 5, 6,33,34],
- [27,28,33,12], [ 5,28,33,12], [27, 6,33,12], [ 5, 6,33,12],
- [27,28,11,34], [ 5,28,11,34], [27, 6,11,34], [ 5, 6,11,34],
- [27,28,11,12], [ 5,28,11,12], [27, 6,11,12], [ 5, 6,11,12],
- [25,26,31,32], [25, 6,31,32], [25,26,31,12], [25, 6,31,12],
- [15,16,21,22], [15,16,21,12], [15,16,11,22], [15,16,11,12],
- [29,30,35,36], [29,30,11,36], [ 5,30,35,36], [ 5,30,11,36],
- [39,40,45,46], [ 5,40,45,46], [39, 6,45,46], [ 5, 6,45,46],
- [25,30,31,36], [15,16,45,46], [13,14,19,20], [13,14,19,12],
- [17,18,23,24], [17,18,11,24], [41,42,47,48], [ 5,42,47,48],
- [37,38,43,44], [37, 6,43,44], [13,18,19,24], [13,14,43,44],
- [37,42,43,48], [17,18,47,48], [13,18,43,48], [ 1, 2, 7, 8]],
- [[27,28,33,34], [49,50,55,56], [51,52,57,58], [49,52,55,58],
- [63,64,69,70], [65,66,71,72], [51,52,69,70], [ 5, 6,33,12],
- [61,62,67,68], [49,50,67,68], [53,54,59,60], [ 5, 6,11,34],
- [61,64,67,70], [ 5,28,11,12], [27, 6,11,12], [ 5, 6,11,12],
- [25,26,31,32], [25, 6,31,32], [25,26,31,12], [25, 6,31,12],
- [15,16,21,22], [15,16,21,12], [15,16,11,22], [15,16,11,12],
- [29,30,35,36], [29,30,11,36], [ 5,30,35,36], [ 5,30,11,36],
- [39,40,45,46], [ 5,40,45,46], [39, 6,45,46], [ 5, 6,45,46],
- [25,30,31,36], [15,16,45,46], [13,14,19,20], [13,14,19,12],
- [17,18,23,24], [17,18,11,24], [41,42,47,48], [ 5,42,47,48],
- [37,38,43,44], [37, 6,43,44], [13,18,19,24], [13,14,43,44],
- [37,42,43,48], [17,18,47,48], [13,18,43,48], [ 1, 2, 7, 8]]
- ].freeze
- def self.autotile(filename)
- key = "Graphics/Autotiles/#{filename}"
- if !@cache.include?(key) || @cache[key].disposed?
- # Cache the autotile graphic.
- @cache[key] = (filename == '') ? Bitmap.new(128, 96) : Bitmap.new(key)
- # Cache each configuration of this autotile.
- new_bm = self.format_autotiles(@cache[key], filename)
- @cache[key] = [@cache[key].dispose] && new_bm
- end
- return @cache[key]
- end
- def self.format_autotiles(bitmap, filename)
- if bitmap.height > 32
- frames = bitmap.width / 96
- index = bitmap.height == 192 ? AUTO_INDEX[1] : AUTO_INDEX[0]
- template = Bitmap.new(256*frames,192)
- frames.times {|a| (0...6).each { |i| (0...8).each { |j|
- index[8*i+j].each { |number|
- number -= 1
- x, y = 16 * (number % 6), 16 * (number / 6)
- ox, oy = (32 * j + x % 32) + (a * 256), 32 * i + y % 32
- rect = Rect.new(x + (a * 96), y, 16, 16)
- template.blt(ox, oy, bitmap, rect)
- }}}}
- return template
- else
- return bitmap
- end
- end
- end
- #==============================================================================
- # ** Resolution
- #==============================================================================
- class Viewport
- def resize(*args)
- # Resize the viewport. Can call with (X, Y, WIDTH, HEIGHT) or (RECT).
- self.rect = args[0].is_a?(Rect) ? args[0] : Rect.new(*args)
- end
- def update_viewport_sizes
- w = $resolution.width
- h = $resolution.height
- _w = ($game_map.width * 32 * $game_map.zoom_x)
- _h = ($game_map.height * 32 * $game_map.zoom_y)
- dx = w > _w ? ((w - _w).abs / 32.0) * 16 : 0
- dw = [w, $game_map.width * 32 * $game_map.zoom_x].min
- dy = h > _h ? ((h - _h).abs / 32.0) * 16 : 0
- dh = [h, $game_map.height * 32 * $game_map.zoom_y].min
- resize(Rect.new(dx, dy, dw, dh))
- end
- end
- #==============================================================================
- # ** Tilemap
- #==============================================================================
- class Tilemap
- attr_accessor :tileset, :autotiles, :map_data, :priorities, :ground_sprite
- attr_accessor :zoom_x, :zoom_y
- #---------------------------------------------------------------------------
- # Initialize
- #---------------------------------------------------------------------------
- def initialize(viewport = nil)
- @viewport = viewport
- @layer_sprites = []
- # [[ANIMATION_DRAW_INDEX, CURRENT_LOGICAL_FRAME], ... ]
- @autotile_frame = []
- # [[DATA_FROM_CONFIGURATION_ABOVE], ... ]
- @autotile_framedata = []
- @zoom_x = @zoom_y = 1
- # Ensures that the bitmap width accounts for an extra tile
- # and is divisible by 32
- bitmap_width = (($resolution.width / 32.0).ceil + 1) * 32
- # Create the priority layers
- (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS).times do |i|
- s = Sprite.new(@viewport)
- s.y = i*32 - (MAX_PRIORITY_LAYERS - 1) * 32 * @zoom_y
- s.z = 32 * (i+2)
- s.zoom_x = @zoom_x
- s.zoom_y = @zoom_y
- s.bitmap = Bitmap.new(bitmap_width, MAX_PRIORITY_LAYERS * 32)
- @layer_sprites.push(s)
- end
- # Same reasons as bitmap_width, but for height
- bitmap_height = (($resolution.height / 32.0).ceil + 1) * 32
- # Create the ground layer (priority 0)
- s = Sprite.new(@viewport)
- s.bitmap = Bitmap.new(bitmap_width, bitmap_height)
- @ground_sprite = s
- @ground_sprite.z = 0
- @ground_sprite.zoom_x = @zoom_x
- @ground_sprite.zoom_y = @zoom_y
- # Initialize Autotile data
- $game_map.autotile_names.each_index do |i|
- filename = $game_map.autotile_names[i]
- # Get animation frame rate of the autotile
- frames = autotile_framerate(filename)
- # If autotile doesn't animate
- if frames.nil?
- @autotile_frame[i] = [0,0]
- @autotile_framedata[i] = nil
- else
- # Save the frame rate data
- @autotile_framedata[i] = frames
- # Determine how long one animation cycle takes and indicate at what
- # time the next frame of animation occurs
- total = 0
- frame_checkpoints = []
- frames.each_index{|j| frame_checkpoints[j] = (total += frames[j]) }
- # Get animation frame for this autotile based on game time passed
- current_frame = Graphics.frame_count % total
- frame_checkpoints.each_index do |j|
- c = frame_checkpoints[j]
- if c && c > current_frame
- (@autotile_frame[i] = [j, c - current_frame]) && break
- end
- end
- end
- end
- # Initialize remaining variables
- @first_update = true
- @autotiles = []
- @empty = Color.new(0,0,0,0)
- @old_ox = @old_oy = 0
- @ox = @oy = 0
- @shift = 0
- # Set up the DLL calls
- @@update = Win32API.new("XPATilemap","DrawMapsBitmap2","pppp","i")
- @@autotile_update = Win32API.new("XPATilemap","UpdateAutotiles","pppp","i")
- @@initial_draw = Win32API.new("XPATilemap","DrawMapsBitmap","pppp","i")
- init_empty_tile = Win32API.new("XPATilemap","InitEmptyTile","l","i")
- init_empty_tile.call((@empty_tile = Bitmap.new(32,32)).object_id)
- end
- #---------------------------------------------------------------------------
- # Dispose tilemap
- #---------------------------------------------------------------------------
- def dispose
- @layer_sprites.each{|sprite| sprite.dispose}
- @ground_sprite.dispose
- end
- #---------------------------------------------------------------------------
- # Zoom x
- #---------------------------------------------------------------------------
- def zoom_x=(value)
- return if @zoom_x == value
- (@layer_sprites + [@ground_sprite]).each do |sprite|
- sprite.x *= value / zoom_x
- sprite.zoom_x = value
- end
- @zoom_x = value
- end
- #---------------------------------------------------------------------------
- # Zoom y
- #---------------------------------------------------------------------------
- def zoom_y=(value)
- return if @zoom_y == value
- (@layer_sprites + [@ground_sprite]).each do |sprite|
- sprite.y *= value / zoom_y
- sprite.zoom_y = value
- end
- @zoom_y = value
- end
- #---------------------------------------------------------------------------
- # Check if disposed tilemap
- #---------------------------------------------------------------------------
- def disposed?
- return @layer_sprites[0].disposed?
- end
- #---------------------------------------------------------------------------
- # Get viewport
- #---------------------------------------------------------------------------
- def viewport
- return @viewport
- end
- #---------------------------------------------------------------------------
- # Update tilemap graphics
- #---------------------------------------------------------------------------
- def update
- # t = Time.now
- autotile_need_update = []
- # Update autotile animation frames
- for i in 0..6
- autotile_need_update[i] = false
- # If this autotile doesn't animate, skip
- next if @autotile_framedata[i].nil?
- # Reduce frame count
- @autotile_frame[i][1] -= 1
- # Autotile requires update
- if (autotile = @autotile_frame[i])[1] == 0
- autotile[0] = (autotile[0] + 1) % @autotile_framedata[i].size
- autotile[1] = @autotile_framedata[i][autotile[0]]
- autotile_need_update[i] = true
- end
- end
- # If $game_map.data[]= script call was used, force redraw on entire map
- if self.map_data.changed
- @first_update = true
- self.map_data.changed = false
- end
- # Stop the update unless updating for first time or there are no shifting
- return if (!@first_update && @shift==0 &&
- autotile_need_update.index(true).nil?)
- # Set up the array for the priority layers
- layers = [@layer_sprites.size + 1]
- # Insert higher priority layers into the array in order
- # (least to most y-value sprite)
- @layer_sprites.each{|sprite| layers.push(sprite.bitmap.object_id) }
- # Insert ground layer last in the array
- layers.push(@ground_sprite.bitmap.object_id)
- # Load autotile bitmap graphics into array
- tile_bms = [self.tileset.object_id]
- self.autotiles.each{|autotile| tile_bms.push(autotile.object_id) }
- # Store autotile animation frame data
- autotiledata = []
- for i in 0..6
- autotiledata.push(@autotile_frame[i][0])
- autotiledata.push(autotile_need_update[i] ? 1 : 0)
- end
- # Fills in remaining information of other tilemaps
- misc_data = [@ox + $game_screen.shake.to_i, @oy, self.map_data.object_id,
- self.priorities.object_id, @shift, MAX_PRIORITY_LAYERS]
- process = [layers.pack("L*"), tile_bms.pack("L*"),
- autotiledata.pack("L*"), misc_data.pack("L*")]
- # If forcing fresh redraw of the map (or drawing for first time)
- if @first_update
- # Initialize layer sprite positions and clear them for drawing
- @layer_sprites.each_index{|i| layer = @layer_sprites[i]
- layer.bitmap.clear
- layer.x = -@ox % 32
- if layer.x <= -32 + $game_screen.shake.to_i
- layer.x += 32
- elsif layer.x > $game_screen.shake.to_i
- layer.x -= 32
- end
- layer.y = (i * 32) - (@oy % 32) - (MAX_PRIORITY_LAYERS-1) * 32
- layer.x *= @zoom_x
- layer.y *= @zoom_y
- layer.zoom_x = @zoom_x
- layer.zoom_y = @zoom_y
- }
- @ground_sprite.bitmap.clear
- @ground_sprite.x = -(@ox % 32)
- if @ground_sprite.x <= -32 + $game_screen.shake.to_i
- @ground_sprite.x += 32
- elsif @ground_sprite.x > $game_screen.shake.to_i
- @ground_sprite.x -= 32
- end
- @ground_sprite.y = -(@oy % 32)
- @ground_sprite.x *= @zoom_x
- @ground_sprite.y *= @zoom_y
- @ground_sprite.zoom_x = @zoom_x
- @ground_sprite.zoom_y = @zoom_y
- # Turn off flag to prevent calling this portion of code again
- @first_update = false
- # Make DLL call
- @@initial_draw.call(*process)
- elsif @shift != 0
- # Update for shifting
- @@update.call(*process)
- end
- # Check for autotile updates
- autotile_need_update.index(true).nil? || @@autotile_update.call(*process)
- # Reset shift flag
- @shift = 0
- #puts Time.now - t
- end
- #---------------------------------------------------------------------------
- # Return if tilemap is visible
- #---------------------------------------------------------------------------
- def visible
- return layer_sprites[0].visible
- end
- #---------------------------------------------------------------------------
- # Show or hide tilemap
- #---------------------------------------------------------------------------
- def visible=(bool)
- @layer_sprites.each{|sprite| sprite.visible = bool}
- @ground_sprite.visible = bool
- end
- #---------------------------------------------------------------------------
- # Shift tilemap horizontally
- #---------------------------------------------------------------------------
- def ox=(ox)
- # No shift = no need to continue
- if !$game_screen.shaking? && -(@ox % 32) * @zoom_x != @ground_sprite.x
- @first_update = true
- end
- ox = ox.round
- return if @ox == ox && !$game_screen.shaking?
- # Compute difference and save change
- diff = @ox - ox
- @ox = ox
- # If forcing redraw, no need to shift layer sprites around
- return if @first_update
- # If shift is too big, force redraw
- if diff.abs > 32
- return @first_update = true
- end
- # Shift sprites
- @ground_sprite.x += (diff * @zoom_x)
- @layer_sprites.each{|sprite| sprite.x += (diff * @zoom_x)}
- # If sprites are out of bounds, reposition and redraw (make DLL call)
- if @ground_sprite.x <= (-32 + $game_screen.shake.to_i) * @zoom_x
- @ground_sprite.x += (32 * @zoom_x)
- bitmap = @ground_sprite.bitmap
- bitmap.fill_rect(0, 0, 32, bitmap.height, @empty)
- @layer_sprites.each do |s|
- s.bitmap.fill_rect((s.x+=(32*@zoom_x))*0,0,32,s.bitmap.height,@empty)
- end
- @shift += 1 # Redraw right column
- elsif @ground_sprite.x > (0 + $game_screen.shake.to_i) * @zoom_x
- @ground_sprite.x -= (32 * @zoom_x)
- bitmap = @ground_sprite.bitmap
- bitmap.fill_rect(bitmap.width - 32, 0, 32, bitmap.height, @empty)
- @layer_sprites.each do |s|
- s.x -= (32 * @zoom_x)
- s.bitmap.fill_rect(s.bitmap.width - 32,0,32,s.bitmap.height,@empty)
- end
- @shift += 2 # Redraw left column
- end
- end
- #---------------------------------------------------------------------------
- # Shift tilemap vertically
- #---------------------------------------------------------------------------
- def oy=(oy)
- if !$game_screen.shaking? && -(@oy % 32) * @zoom_y != @ground_sprite.y
- @first_update = true
- end
- oy = oy.round
- return if @oy == oy
- diff = @oy - oy
- @oy = oy
- # If shift is too big, force redraw
- return if @first_update
- if diff.abs > 32
- return @first_update = true
- end
- # Shift sprites
- @ground_sprite.y += (diff * @zoom_y)
- @layer_sprites.each{ |sprite|
- sprite.y += (diff * @zoom_y)
- sprite.z += diff
- }
- # If ground is out of bounds, reshift and redraw (make DLL call)
- if @ground_sprite.y <= -32 * @zoom_y
- @ground_sprite.y += (32 * @zoom_y)
- @shift += 4 # Redraw bottom row
- elsif @ground_sprite.y > 0
- @ground_sprite.y -= (32 * @zoom_y)
- @shift += 8 # Redraw top row
- end
- # If layer is too far up screen, need to move it down
- if @layer_sprites[0].y <= -(MAX_PRIORITY_LAYERS * 32) * @zoom_y
- shift_amt = (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS) * 32
- layer = @layer_sprites.shift
- layer.y += shift_amt * @zoom_y
- layer.z += shift_amt
- layer.bitmap.clear
- @layer_sprites.push(layer)
- end
- # If layer is too far down screen, need to move it up
- if @layer_sprites[-1].y > (($resolution.height/32.0).ceil * 32) * @zoom_y
- shift_amt = (($resolution.height/32.0).ceil + MAX_PRIORITY_LAYERS) * -32
- layer = @layer_sprites.pop
- layer.y += shift_amt * @zoom_y
- layer.z += shift_amt
- layer.bitmap.clear
- @layer_sprites.unshift(layer)
- end
- end
- end
- #==============================================================================
- # ** Game_Character
- #------------------------------------------------------------------------------
- # This class deals with characters. It's used as a superclass for the
- # determinants and map scrolling. Refer to "$game_player" for the one
- # Game_Player and Game_Event classes.
- #==============================================================================
- class Game_Character
- $@ || alias_method(:screen_x_zoom, :screen_x)
- $@ || alias_method(:screen_y_zoom, :screen_y)
- $@ || alias_method(:screen_z_zoom, :screen_z)
- define_method(:screen_x) {|*args| screen_x_zoom(*args) * $game_map.zoom_x }
- define_method(:screen_y) {|*args| screen_y_zoom(*args) * $game_map.zoom_y }
- def screen_z(*args)
- return 999 if @always_on_top
- return $1.to_i if self.is_a?(Game_Event) &&
- self.instance_variable_get(:@event).name[/\<Z:\s*([-]?\d+)\s*\>/i]
- case @character_name
- when '178-Switch01' then return 0
- when '180-Switch03' then return 0
- when '181-Switch04' then return 0
- when '199-Support07' then return 0
- end
- return screen_z_zoom(*args)
- end
- end
- #==============================================================================
- # ** Game_Player
- #==============================================================================
- class Game_Player
- def center(x, y)
- # Recalculate the screen center based on the new resolution.
- max_x = $game_map.map_edge.at(0)
- max_y = $game_map.map_edge.at(1)
- $game_map.display_x = [0, [x * 128 - CENTER_X, max_x].min].max
- $game_map.display_y = [0, [y * 128 - CENTER_Y, max_y].min].max
- end
- end
- #==============================================================================
- # ** Game_Map
- #==============================================================================
- class Game_Map
- $@ || alias_method(:zer0_map_edge_setup, :setup)
- $@ || alias_method(:drg_width_adjust, :width)
- $@ || alias_method(:drg_height_adjust, :height)
- $@ || alias_method(:drg_update_zooming, :update)
- attr_reader :map_edge
- define_method(:zoom_x) { [[@zoom_x ||= 1,12].min, 0.5].max }
- define_method(:zoom_y) { [[@zoom_y ||= 1,12].min, 0.5].max }
- define_method(:width) { @map ? drg_width_adjust : 0 }
- define_method(:height) { @map ? drg_height_adjust : 0 }
- define_method(:zooming?) { (@zoom_duration ||= 0) > 0 }
- def setup(map_id)
- zer0_map_edge_setup(map_id)
- refresh_map_edge
- end
- def refresh_map_edge
- # Find the displayed area of the map in tiles. No calculating every step.
- @map_edge = [[width*zoom_x-($resolution.width/32.0),0].max/zoom_x,
- [height*zoom_y-($resolution.height/32.0),0].max/zoom_y]
- @map_edge.collect! {|size| (size * 128).ceil }
- Game_Player.const_set(:CENTER_X,(($resolution.width/2) / zoom_x - 16) * 4)
- Game_Player.const_set(:CENTER_Y,(($resolution.height/2) / zoom_y - 16) * 4)
- s = $scene.instance_variable_get(:@spriteset)
- s.update_viewport_sizes if s.respond_to?(:update_viewport_sizes)
- end
- def scroll_down(distance)
- # Find point that the map edge meets the screen edge, using custom size.
- @display_y = [@display_y + distance, @map_edge[1]].min
- end
- def scroll_right(distance)
- # Find point that the map edge meets the screen edge, using custom size.
- @display_x = [@display_x + distance, @map_edge[0]].min
- end
- def zoom(*zoom)
- if zoom.size == 1
- zoom = (zoom.first)
- elsif zoom.size == 3
- x,y,zoom = zoom
- end
- return unless zoom.is_a?(Numeric)
- @zoom_x = @zoom_y = zoom
- @zoom_x , @zoom_y = self.zoom_x, self.zoom_y
- refresh_map_edge
- $game_player.center(x,y) if x && y
- end
- def start_zoom(x,y, zoom_target, duration=20)
- @x_zoom, @y_zoom = x, y
- @zoom_target = zoom_target * 1.0
- @zoom_duration = @zoom_x == @zoom_target ? 0 : duration
- if @zoom_duration == 0 && @zoom_x != @zoom_target
- zoom(*[@x_zoom,@y_zoom,zoom_target].compact)
- end
- end
- def update_zooming
- if zooming?
- d = @zoom_duration
- power = (@zoom_x * (d - 1) + @zoom_target) / d
- args = [@x_zoom,@y_zoom,power].compact
- zoom(*args)
- @zoom_duration -= 1
- end
- end
- def update(*args)
- drg_update_zooming(*args)
- update_zooming
- end
- end
- #==============================================================================
- # ** Plane
- #==============================================================================
- Object.send(:remove_const, :Plane)
- class Plane < Sprite
- attr_reader :bitmap
- def z=(z)
- # Change the Z value of the viewport, not the sprite.
- super(z * 1000)
- end
- def ox=(ox)
- # Have viewport stay in loop on X-axis.
- super(ox % bitmap.width) if bitmap.is_a?(Bitmap)
- end
- def oy=(oy)
- # Have viewport stay in loop on Y-axis.
- super(oy % bitmap.height) if bitmap.is_a?(Bitmap)
- end
- def dispose
- @plane && (@plane.disposed? || @plane.dispose)
- super unless disposed?
- end
- def bitmap=(tile)
- return if @bitmap == tile
- @bitmap = tile
- return super(@bitmap) unless tile.is_a?(Bitmap)
- # Calculate the number of tiles it takes to span screen in both directions.
- xx = 1 + ($resolution.width.to_f / tile.width ).ceil
- yy = 1 + ($resolution.height.to_f / tile.height).ceil
- # Create appropriately sized bitmap, then tile across it with source image.
- @plane && (@plane.disposed? || @plane.dispose)
- @plane = Bitmap.new(@bitmap.width * xx, @bitmap.height * yy)
- (0..xx).each {|x| (0..yy).each {|y|
- @plane.blt(x * @bitmap.width, y * @bitmap.height, @bitmap, @bitmap.rect)
- }}
- # Set the bitmap to the sprite through its super class (Sprite).
- super(@plane)
- end
- # Undefine methods dealing with coordinates (defined in super) to do nothing.
- undef :x, :x=, :y, :y= if method_defined?(:x)
- end
- class CRPlane < Plane; end
- #==============================================================================
- # ** Table
- #==============================================================================
- class Table
- attr_accessor :changed
- $@ || alias_method(:flag_changes_to_set, :"[]=")
- def []=(*args)
- @changed = true if args.size == 4
- flag_changes_to_set(*args)
- end
- end
- #==============================================================================
- # ** RPG::Weather
- #==============================================================================
- class RPG::Weather
- if WEATHER_ADJUSTMENT
- $@ || alias_method(:add_more_weather_sprites, :initialize)
- def initialize(vp = nil)
- add_more_weather_sprites(vp)
- total_sprites = $resolution.width * $resolution.height / 7680
- if total_sprites > 40
- for i in 1..(total_sprites - 40)
- sprite = Sprite.new(vp)
- sprite.z = 1000
- sprite.visible = false
- sprite.opacity = 0
- @sprites.push(sprite)
- end
- end
- end
- def type=(type)
- return if @type == type
- @type = type
- bitmap = case @type
- when 1 then @rain_bitmap
- when 2 then @storm_bitmap
- when 3 then @snow_bitmap
- end
- for i in 1..@sprites.size
- sprite = @sprites[i]
- if sprite != nil
- sprite.visible = (i <= @max)
- sprite.bitmap = bitmap
- end
- end
- end
- def max=(max)
- return if @max == max;
- @max = [[max, 0].max, @sprites.size].min
- for i in 1..@sprites.size
- sprite = @sprites[i]
- if sprite != nil
- sprite.visible = (i <= @max)
- end
- end
- end
- end # WEATHER_ADJUSTMENT
- def update
- return if @type == 0
- for i in 1..@max
- sprite = @sprites[i]
- if sprite == nil
- break
- end
- if @type == 1
- sprite.x -= 2
- sprite.y += 16
- sprite.opacity -= 8
- end
- if @type == 2
- sprite.x -= 8
- sprite.y += 16
- sprite.opacity -= 12
- end
- if @type == 3
- sprite.x -= 2
- sprite.y += 8
- sprite.opacity -= 8
- end
- x = sprite.x - @ox
- y = sprite.y - @oy
- if sprite.opacity < 64
- sprite.x = rand($resolution.width + 100) - 100 + @ox
- sprite.y = rand($resolution.width + 200) - 200 + @oy
- sprite.opacity = 160 + rand(96)
- end
- end
- end
- end
- #==============================================================================
- # ** Game_Screen
- #==============================================================================
- class Game_Screen
- #--------------------------------------------------------------------------
- # * Set Weather
- # type : type
- # power : strength
- # duration : time
- #--------------------------------------------------------------------------
- def weather(type, power, duration)
- @weather_type_target = type
- if @weather_type_target != 0
- @weather_type = @weather_type_target
- end
- if @weather_type_target == 0
- @weather_max_target = 0.0
- else
- if WEATHER_ADJUSTMENT
- num = $resolution.width * $resolution.height / 76800.0
- else
- num = 4.0
- end
- @weather_max_target = (power + 1) * num
- end
- @weather_duration = duration
- if @weather_duration == 0
- @weather_type = @weather_type_target
- @weather_max = @weather_max_target
- end
- end
- def shaking?
- return @shake_duration > 0 || @shake != 0
- end
- end
- #==============================================================================
- # ** Spriteset_Map
- #==============================================================================
- class Spriteset_Map
- $@ || alias_method(:init_for_centered_small_maps , :initialize)
- $@ || alias_method(:update_for_zoom, :update)
- #---------------------------------------------------------------------------
- # Resize and reposition viewport so that it fits smaller maps
- #---------------------------------------------------------------------------
- def update_viewport_sizes
- @viewport1.update_viewport_sizes
- @viewport2.update_viewport_sizes
- @viewport3.update_viewport_sizes
- end
- def initialize
- init_for_centered_small_maps
- update_viewport_sizes
- end
- def update
- if @old_fog_zoom_x
- @fog.zoom_x = @old_fog_zoom_x
- @fog.zoom_y = @old_fog_zoom_y
- @panorama.zoom_x = @old_panorama_zoom_x
- @panorama.zoom_y = @old_panorama_zoom_y
- end
- @tilemap.zoom_x = $game_map.zoom_x
- @tilemap.zoom_y = $game_map.zoom_y
- update_for_zoom
- @old_fog_zoom_x = @fog.zoom_x
- @old_fog_zoom_y = @fog.zoom_y
- @old_panorama_zoom_x = @panorama.zoom_x
- @old_panorama_zoom_y = @panorama.zoom_y
- @fog.zoom_x *= $game_map.zoom_x
- @fog.zoom_y *= $game_map.zoom_y
- @panorama.zoom_x *= $game_map.zoom_x
- @panorama.zoom_y *= $game_map.zoom_y
- end
- end
- #==============================================================================
- # ** Sprite_Character
- #------------------------------------------------------------------------------
- # This sprite is used to display the character.It observes the Game_Character
- # class and automatically changes sprite conditions.
- #==============================================================================
- class Sprite_Character
- $@ || alias_method(:zoom_update_character, :update)
- def update(*args)
- if @old_character_zoom_x
- self.zoom_x = @old_character_zoom_x
- self.zoom_y = @old_character_zoom_y
- end
- zoom_update_character(*args)
- @old_character_zoom_x = self.zoom_x
- @old_character_zoom_y = self.zoom_y
- self.zoom_x *= $game_map.zoom_x
- self.zoom_y *= $game_map.zoom_y
- end
- end
- #------------------------------------------------------------------------------
- $resolution = Resolution.new
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement