Dynamic Parallax Trees Tutorial

● ARCHIVED · READ-ONLY
Started by WinglessRM 3 posts View original ↗
  1. Hello there VX Ace community.Today i'm going to be showing my method Parallaxing Dynamic trees that are simultaneously on the ground layer and the parallax layer.Essentially the purpose of this guide is to show how to create trees that have their roots under the player, the trunk in front of the player and have their leaves over the player.
     
    Scripts needed
     
    Tsukihime Map Screenshot
     

    Spoiler
    =begin
    #===============================================================================
    Title: Map Screenshot
    Author: Hime
    Date: Apr 15, 2013
    --------------------------------------------------------------------------------
    ** Change log
    Apr 15, 2013
    - updated script to use GDI+ interface
    - added support for region map overlay and passage map overlay
    Apr 6, 2013
    - fixed bug where drawing events crashed the game
    Apr 2, 2013
    - map data is now setup by an instance of Game_Map, to account for custom
    map scripts adding to the map
    Jul 27
    - Export dirNames are now optional
    May 28
    - updated overlay mapping compatibility to draw the overlays
    based on the player's current position
    - fixed issue where import hash was commented out
    - Added support for Yami's overlay mapping
    May 24, 2012
    - fixed large characters
    - some optimizations for calculating bounds and dimensions
    May 5, 2012
    - fixed waterfall autotile
    - added screenshot feature
    May 4, 2012
    - fixed tiles with alpha channel
    - fixed shadows
    - fixed wall autotiles
    May 1, 2012
    - fixed wall autotile, although there is still an issue with some tiles
    Apr 29, 2012
    - fixed shadow map drawing
    - added region highlighting
    - added damage tile highlighting
    Apr 28, 2012
    - Initial Release
    ------------------------------------------------------------------------------
    ** Description

    This script allows you to take a full image of any of your game's maps
    and export. An image of the map is referred to as a "mapshot" (as opposed to
    screenshot).

    The script provides various configuration options to control what kinds of
    things you want to see on your map, such as events, vehicles, region ID's, or
    specific tile properties.

    ------------------------------------------------------------------------------
    ** Usage

    The default key for taking a mapshot is F7. This can be changed in the
    configuration section.

    To take a mapshot, first start the game, and then hit F7.
    A message will appear informing you that a mapshot was successfully taken.

    Alternatively, you can use script calls to take mapshots.

    Map_Saver.new(map_id).export

    Aside from exporting images, you are able to use the image that the
    map saver captures.

    ms = Map_Saver.new(map_id)
    bmp = ms.map_image

    This gives you a reference to a Bitmap object that contains an image of
    your map.
    --------------------------------------------------------------------------------
    ** Credits

    Cremno
    -GDI+ interface code
    Cidiomar
    -for drawing autotiles and shadows,
    -providing efficient bmp and png exporters
    Moon
    -auto-tile related info
    Mephistox
    -testing and suggestions
    ================================================================================
    =end
    $imported = {} if $imported.nil?
    $imported["TH_MapSaver"] = true
    #===============================================================================
    # ** Configuration
    #===============================================================================
    module TH
    module Map_Saver

    #Mapshot options. This takes an image of the entire map
    Mapshot_Button = Input::F7
    Mapshot_Scale = 1

    #Screenshot options. This takes an image of the visible map
    Screenshot_Button = Input::F6
    Screenshot_Scale = 1

    #Folder that the map will be exported to
    Mapshot_Directory = "Mapshots"
    Screenshot_Directory = "Screenshots"

    # format you want to export to. You should stick with png.
    # Options: [bmp, png]
    Export_Format = "png"

    # Sprite draw options
    Draw_Events = false
    Draw_Player = false
    Draw_Followers = false
    Draw_Vehicles = false

    #Should shadows be drawn? What color?
    Draw_Shadow = true
    Shadow_Color = Color.new(0, 0, 0, 128)

    # Should regions be drawn? Requires "Region Overlay Map" script
    Draw_Regions = false

    # Should passage settings be drawn? Requires "Passage Overlay Map" script
    Draw_Passages = false

    #Should damage tiles be highlighted? What color?
    Highlight_Damage = true
    Damage_Color = Color.new(128, 0, 0, 128)
    end
    end

    #==============================================================================
    # ** Module: Map_Tiles
    # Contains data and methods useful for working with maps and tiles
    #==============================================================================

    module Map_Tiles
    AUTOTILE_PARTS = [[18,17,14,13], [ 2,14,17,18], [13, 3,17,18], [ 2, 3,17,18],
    [13,14,17, 7], [ 2,14,17, 7], [13, 3,17, 7], [ 2, 3,17, 7],
    [13,14, 6,18], [ 2,14, 6,18], [13, 3, 6,18], [ 2, 3, 6,18],
    [13,14, 6, 7], [ 2,14, 6, 7], [13, 3, 6, 7], [ 2, 3, 6, 7],
    [16,17,12,13], [16, 3,12,13], [16,17,12, 7], [12, 3,16, 7],
    [10, 9,14,13], [10, 9,14, 7], [10, 9, 6,13], [10, 9, 6, 7],
    [18,19,14,15], [18,19, 6,15], [ 2,19,14,15], [ 2,19, 6,15],
    [18,17,22,21], [ 2,17,22,21], [18, 3,22,21], [ 2, 3,21,22],
    [16,19,12,15], [10, 9,22,21], [ 8, 9,12,13], [ 8, 9,12, 7],
    [10,11,14,15], [10,11, 6,15], [18,19,22,23], [ 2,19,22,23],
    [16,17,20,21], [16, 3,20,21], [ 8,11,12,15], [ 8, 9,20,21],
    [16,19,20,23], [10,11,22,23], [ 8,11,20,23], [ 0, 1, 4, 5]]
    WATERFALL_PIECES = [[ 2, 1, 6, 5], [ 0, 1, 4, 5], [ 2, 3, 6, 7], [0, 3, 4, 7]]
    WALL_PIECES = [[10, 9, 6, 5], [ 8, 9, 4, 5], [ 2, 1, 6, 5], [ 0, 1, 4, 5],
    [10,11, 6, 7], [ 8,11, 4, 7], [ 2, 3, 6, 7], [ 0, 3, 4, 7],
    [10, 9,14,13], [ 8, 9,12,13], [ 2, 1,14,13], [ 0, 1,12,13],
    [10,11,14,15], [8, 11,12,15], [ 2, 3,14,15], [ 0, 3,12,15]]

    A1_TILES = [[0, 0], [0, 96], [192, 0], [192, 96],
    [256, 0], [448, 0], [256, 96], [448, 96],
    [0, 192], [192, 192], [0, 288], [192, 288],
    [256, 192], [448, 192], [256, 288], [448, 288]]


    #--------------------------------------------------------------------------
    # * Checks if a tile is a wall
    #--------------------------------------------------------------------------
    def is_wall?(data)
    return true if data.between?(2288, 2335)
    return true if data.between?(2384, 2431)
    return true if data.between?(2480, 2527)
    return true if data.between?(2576, 2623)
    return true if data.between?(2672, 2719)
    return true if data.between?(2768, 2815)
    return true if data.between?(4736, 5119)
    return true if data.between?(5504, 5887)
    return true if data.between?(6272, 6655)
    return true if data.between?(7040, 7423)
    return true if data > 7807
    false
    end
    #--------------------------------------------------------------------------
    # * Checks if a tile is roof
    #--------------------------------------------------------------------------
    def is_roof?(data)
    return true if data.between?(4352, 4735)
    return true if data.between?(5120, 5503)
    return true if data.between?(5888, 6271)
    return true if data.between?(6656, 7039)
    return true if data.between?(7424, 7807)
    false
    end
    #--------------------------------------------------------------------------
    # * Checks if a tile is soil
    #--------------------------------------------------------------------------
    def is_soil?(data)
    return true if data.between?(2816, 4351) && !is_table?(data)
    return true if data > 1663 && !is_stair?(data)
    false
    end
    #--------------------------------------------------------------------------
    # * Checks if a tile is a stair
    #--------------------------------------------------------------------------
    def is_stair?(data)
    return true if data.between?(1541, 1542)
    return true if data.between?(1549, 1550)
    return true if data.between?(1600, 1615)
    false
    end
    #--------------------------------------------------------------------------
    # * Checks if a tile is a table
    #--------------------------------------------------------------------------
    def is_table?(data)
    return true if data.between?(3152, 3199)
    return true if data.between?(3536, 3583)
    return true if data.between?(3920, 3967)
    return true if data.between?(4304, 4351)
    false
    end

    #--------------------------------------------------------------------------
    # * The tileset to be used
    #--------------------------------------------------------------------------
    def tileset
    $data_tilesets[@tileset_id]
    end

    #--------------------------------------------------------------------------
    # * Region ID
    #--------------------------------------------------------------------------
    def region_id(x, y)
    valid?(x, y) ? @map.data[x, y, 3] >> 8 : 0
    end

    #--------------------------------------------------------------------------
    # * Gets all of the tiles for each layer at position x,y
    #--------------------------------------------------------------------------
    def layered_tiles(x, y)
    [2, 1, 0].collect {|z| @map.data[x, y, z] }
    end

    def layered_tiles_flag?(x, y, bit)
    layered_tiles(x, y).any? {|tile_id| tileset.flags[tile_id] & bit != 0 }
    end

    def valid?(x, y)
    x >= 0 && x < width && y >= 0 && y < height
    end

    def damage_floor?(x, y)
    valid?(x, y) && layered_tiles_flag?(x, y, 0x100)
    end

    #--------------------------------------------------------------------------
    # * Specifies which type of autotile is used
    #--------------------------------------------------------------------------
    def auto_tile(id)
    id / 48
    end

    #--------------------------------------------------------------------------
    # * Specifies the specific arrangement of autotiles used
    #--------------------------------------------------------------------------
    def auto_index(id)
    id % 48
    end

    #--------------------------------------------------------------------------
    # * Put the auto-tile pieces together
    #--------------------------------------------------------------------------
    def make_autotile(rects, sx, sy)
    @tile.clear
    for i in 0...4
    @auto_rect.x = (rects % 4) * 16 + sx
    @auto_rect.y = (rects / 4) * 16 + sy
    @tile.blt((i % 2) * 16,(i / 2) * 16, @tilemap, @auto_rect)
    end
    end

    #--------------------------------------------------------------------------
    # * Get auto-tile A1 tiles
    #--------------------------------------------------------------------------
    def autotile_A1(tile_id)
    @tilemap = @bitmaps[0]
    autotile = tile_id / 48
    auto_id = tile_id % 48
    sx, sy = A1_TILES[autotile]
    if is_wall?(tile_id + 2048)
    rects = WATERFALL_PIECES[auto_id]
    else
    rects = AUTOTILE_PARTS[auto_id]
    end
    make_autotile(rects, sx, sy)
    end

    #--------------------------------------------------------------------------
    # * Get auto-tile A2 tiles.
    # 64x96 tiles, 8 per row, 4 rows
    #--------------------------------------------------------------------------
    def autotile_A2(tile_id)
    autotile = tile_id / 48
    auto_id = tile_id % 48
    @tilemap = @bitmaps[1]
    sx = (autotile % 8) * 64
    sy = (autotile / 8 % 4) * 96
    rects = AUTOTILE_PARTS[auto_id]
    make_autotile(rects, sx, sy)
    end

    #--------------------------------------------------------------------------
    # * Get auto-tile A3 tiles.
    # 64x64 tiles, 8 per row, 4 rows
    #--------------------------------------------------------------------------
    def autotile_A3(tid)
    @tilemap = @bitmaps[2]
    sx = (auto_tile(tid) % 8) * 64
    sy = (auto_tile(tid) / 8 % 4) * 64
    rects = WALL_PIECES[auto_index(tid)]
    make_autotile(rects, sx, sy)
    end

    #--------------------------------------------------------------------------
    # * Get auto-tile A4 tiles (walls)
    #--------------------------------------------------------------------------
    def autotile_A4(tile_id)
    @tilemap = @bitmaps[3]
    autotile = tile_id / 48
    auto_id = tile_id % 48
    sx = (autotile % 8) * 64
    sy = (autotile / 16 * 160) + (autotile / 8 % 2) * 96
    if is_wall?(tile_id + 5888)
    rects = WALL_PIECES[auto_id]
    else
    rects = AUTOTILE_PARTS[auto_id]
    end
    make_autotile(rects, sx, sy)
    end

    #--------------------------------------------------------------------------
    # * Get auto-tile A5 tiles (normal)
    #--------------------------------------------------------------------------
    def autotile_A5(tile_id)
    @tilemap = @bitmaps[4]
    sx = (tile_id) % 8 * tilesize
    sy = (tile_id) / 8 * tilesize
    @src_rect.set(sx, sy, tilesize, tilesize)
    @tile.clear
    @tile.blt(0, 0, @tilemap, @src_rect)
    end

    #--------------------------------------------------------------------------
    # * Get normal tiles B, C, D, E
    #--------------------------------------------------------------------------
    def normal_tile(tile_id)
    @tilemap = @bitmaps[5 + tile_id / 256]
    sx = (tile_id / 128 % 2 * 8 + tile_id % 8) * tilesize;
    sy = (tile_id % 256 / 8 % 16) * tilesize;
    @src_rect.set(sx, sy, tilesize, tilesize)
    @tile.clear
    @tile.blt(0, 0, @tilemap, @src_rect)
    end

    #--------------------------------------------------------------------------
    # * Get bitmap for the specified tile id
    #--------------------------------------------------------------------------
    def get_bitmap(id)
    if id < 1024
    normal_tile(id)
    elsif id < 1664
    autotile_A5(id - 1536)
    elsif id < 2816
    autotile_A1(id - 2048)
    elsif id < 4352
    autotile_A2(id - 2816)
    elsif id < 5888
    autotile_A3(id - 4352)
    else
    autotile_A4(id - 5888)
    end
    end
    end

    #==============================================================================
    # **
    #==============================================================================

    class Game_Player < Game_Character

    alias :th_mapsaver_update :update
    def update
    th_mapsaver_update
    if Input.trigger?(TH::Map_Saver::Mapshot_Button)
    s = Map_Saver.new($game_map.map_id)
    s.set_scale(TH::Map_Saver::Mapshot_Scale)
    s.mapshot
    end
    if Input.trigger?(TH::Map_Saver::Screenshot_Button)
    s = Map_Saver.new($game_map.map_id)
    s.set_scale(TH::Map_Saver::Screenshot_Scale)
    s.screenshot
    end
    end
    end

    class Game_Vehicle < Game_Character
    attr_reader :map_id
    end

    class Game_Map
    attr_reader :map
    end

    #==============================================================================
    # **
    #==============================================================================

    class Map_Saver
    include TH::Map_Saver
    include Map_Tiles
    #--------------------------------------------------------------------------
    # * Constants
    #--------------------------------------------------------------------------

    SHADOW_COLOR = TH::Map_Saver::Shadow_Color
    DAMAGE_COLOR = TH::Map_Saver::Damage_Color

    #--------------------------------------------------------------------------
    # * Public instance variables
    #--------------------------------------------------------------------------
    attr_reader :map_image

    def initialize(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y)
    @scale = 1
    @local_x = x
    @local_y = y
    @screen_local = false
    @shadow_bitmap = Bitmap.new(128, 128)
    @draw_layer0 = true
    @draw_layer1 = true
    @draw_layer2 = true
    @draw_events = Draw_Events
    @draw_vehicles = Draw_Vehicles
    @draw_player = Draw_Player
    @draw_followers = Draw_Followers
    @draw_shadow = Draw_Shadow
    @draw_damage = Highlight_Damage
    @draw_regions = Draw_Regions
    @draw_passages = Draw_Passages
    @tile = Bitmap.new(32, 32) #stores the current tile to be drawn
    @tilemap = nil
    @src_rect = Rect.new
    @auto_rect = Rect.new(0, 0, tilesize / 2, tilesize/ 2) #constant
    @tile_rect = Rect.new(0, 0, tilesize, tilesize) #constant
    end

    def load_tilesets
    bitmaps = []
    tileset.tileset_names.each_with_index do |name, i|
    bitmaps = Cache.tileset(name)
    end
    return bitmaps
    end

    #--------------------------------------------------------------------------
    # * Refresh, possibly with a new map
    #--------------------------------------------------------------------------
    def redraw(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y)
    @map_image.dispose if @map_image
    @map_id = map_id
    @local_x = x
    @local_y = y
    @game_map = Game_Map.new
    @game_map.setup(map_id)
    @map = @game_map.map
    @map_info = $data_mapinfos[map_id]
    @screen = $game_map.screen
    @tileset_id = @game_map.tileset.id
    @bitmaps = load_tilesets

    get_bounds
    @map_image = Bitmap.new(@width * tilesize, @height * tilesize)
    draw_map
    scale_map if @scale != 1
    end

    #--------------------------------------------------------------------------
    # * Pre-process. These will never change when drawing the map.
    #--------------------------------------------------------------------------
    def get_bounds
    @start_x = start_x
    @start_y = start_y
    @end_x = end_x
    @end_y = end_y
    @width = width
    @height = height
    @tilesize = tilesize
    end

    def screen_tile_x
    Graphics.width / 32
    end

    def screen_tile_y
    Graphics.height / 32
    end

    #--------------------------------------------------------------------------
    # * Sets the scale for the map
    #--------------------------------------------------------------------------
    def set_scale(scale)
    @scale = scale
    end

    #--------------------------------------------------------------------------
    # * Size of a tile
    #--------------------------------------------------------------------------
    def tilesize
    32
    end

    #--------------------------------------------------------------------------
    # * Width and height of the map, both locally and globally
    #--------------------------------------------------------------------------
    def width
    end_x - @start_x
    end

    def height
    end_y - @start_y
    end

    #--------------------------------------------------------------------------
    # * Starting and end positions, relative to the screen or map
    #--------------------------------------------------------------------------
    def start_x
    @screen_local ? [[$game_player.x - screen_tile_x / 2, @map.width - screen_tile_x].min, 0].max : 0
    end

    def start_y
    @screen_local ? [[$game_player.y - screen_tile_y / 2, @map.height - screen_tile_y].min, 0].max : 0
    end

    def end_x
    @screen_local ? [[screen_tile_x, @local_x + screen_tile_x / 2 + 1].max, @map.width].min : @map.width
    end

    def end_y
    @screen_local ? [[screen_tile_y, @local_y + screen_tile_y / 2 + 1].max, @map.height].min : @map.height
    end

    #--------------------------------------------------------------------------
    # * Draw tile onto image. x and y values are absolute coords. They should
    # be re-mapped based on the start_x and start_y values
    #--------------------------------------------------------------------------
    def draw_tile(x, y, tile, rect)
    ox = (x - @start_x) * tilesize
    oy = (y - @start_y) * tilesize
    @map_image.blt(ox, oy, tile, rect)
    end

    #--------------------------------------------------------------------------
    # * Get bitmap for the specified character
    #--------------------------------------------------------------------------
    def get_character_bitmap(name)
    charmap = Cache.character(name)
    sign = name[/^[\!\$]./]
    if sign && sign.include?('
     
    Yamis overlay Script
     
    Spoiler
    #==============================================================================
    #
    # ▼ Yami Script Ace - Overlay Mapping
    # -- Last Updated: 2011.12.29
    # -- Level: Easy
    # -- Requires: n/a
    # -- Credit: Hanzo Kimura for Original Script
    #
    #==============================================================================

    $imported = {} if $imported.nil?
    $imported["YSA-OverlayMapping"] = true

    #==============================================================================
    # ▼ Updates
    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    # 2011.12.29 - Bugfix for transfer.
    # 2011.12.10 - Started and Finished Script.
    #
    #==============================================================================
    # ▼ Introduction
    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    # This script based on Hanzo Kimura's idea. This will automatically load map's
    # overlay by map ID, and a map can have more than one image per layer, so you
    # don't have to create two or more map just for day/night or when an event occur.
    #
    #==============================================================================
    # ▼ Instructions
    # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    # Create a folder in Graphics and name it Overlay.
    # Put all of your overlay into Graphics/Overlay.
    # Your overlay file will have the name: "Filename Prefix" + Map-ID + "-" + Number
    # which "Filename Prefix" is the one you will config below
    # Map-ID is your map's ID
    # Number is 1, 2, 3, ... using for Overlay Variables.
    #
    # Example: Graphics/Overlay/ground2-1.png
    # Which means this will be ground layer, for map 2, variable = 1
    #
    # Light/Shadow must be .jpg
    # Parallax/Ground must be .png
    #
    #==============================================================================

    module YSA
    module OVERLAY
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # - Overlay Switches -
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # These are switches which are enable overlay layers. Turn them on to show
    # them in your maps.
    #--------------------------------------------------------------------------
    # Default: ON
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    LIGHT_SWITCH = 1 # Turn on/off light layer
    SHADOW_SWITCH = 2 # Turn on/off shadow layer
    PARALLAX_SWITCH = 3 # Turn on/off parallax layer
    GROUND_SWITCH = 4 # Turn on/off ground layer

    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # - Overlay Variables -
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # A map can have more than one image per layer, that means you can have a
    # different light/shadow for day and night, or have a different ground when
    # an event occured.
    #--------------------------------------------------------------------------
    # Default: 1
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    LIGHT_VARIABLE = 2 # Switch to another light
    SHADOW_VARIABLE = 2 # Switch to another shadow
    PARALLAX_VARIABLE = 1 # Switch to another parallax
    GROUND_VARIABLE = 1 # Switch to another ground

    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # - Filename Prefix -
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # This will make this script automatic, it will check if there are layers in
    # overlay folder
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    LIGHT = "light" # Light layer's filename prefix
    SHADOW = "shadow" # Shadow layer's filename prefix
    PARALLAX = "par" # Parallax layer's filename prefix
    GROUND = "ground" # Ground layer's filename prefix

    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # - Overlay Opacity -
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # This will make this script automatic, it will check if there are layers in
    # overlay folder
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    GROUND_OPACITY = 255
    PARALLAX_OPACITY = 255
    LIGHT_OPACITY = 128
    SHADOW_OPACITY = 96
    end #OVERLAY
    end # YSA

    #==============================================================================
    # ▼ Editting anything past this point may potentially result in causing
    # computer damage, incontinence, explosion of user's head, coma, death, and/or
    # halitosis so edit at your own risk.
    #==============================================================================

    #==============================================================================
    # ■ Cache
    #==============================================================================

    module Cache

    #--------------------------------------------------------------------------
    # new method: overlay
    #--------------------------------------------------------------------------
    def self.overlay(filename)
    load_bitmap("Graphics/Overlay/", filename)
    end

    end # Cache

    #==============================================================================
    # ■ DataManager
    #==============================================================================

    module DataManager

    #--------------------------------------------------------------------------
    # alias method: setup_new_game
    #--------------------------------------------------------------------------
    class < def self.setup_new_game
    ovm_setup_new_game
    setup_overlay_mapping
    end

    #--------------------------------------------------------------------------
    # new method: setup_overlay_mapping
    #--------------------------------------------------------------------------
    def self.setup_overlay_mapping
    # Control switches
    $game_switches[YSA::oVERLAY::LIGHT_SWITCH] = true
    $game_switches[YSA::oVERLAY::SHADOW_SWITCH] = true
    $game_switches[YSA::oVERLAY::GROUND_SWITCH] = true
    $game_switches[YSA::oVERLAY::pARALLAX_SWITCH] = true

    # Control variables
    $game_variables[YSA::oVERLAY::LIGHT_VARIABLE] = 1
    $game_variables[YSA::oVERLAY::SHADOW_VARIABLE] = 1
    $game_variables[YSA::oVERLAY::GROUND_VARIABLE] = 1
    $game_variables[YSA::oVERLAY::pARALLAX_VARIABLE] = 1
    end

    end # DataManager

    #==============================================================================
    # ■ Spriteset_Map
    #==============================================================================

    class Spriteset_Map

    #--------------------------------------------------------------------------
    # alias method: initialize
    #--------------------------------------------------------------------------
    alias overlay_initialize initialize
    def initialize
    overlay_initialize
    create_overlay_map
    update
    end

    #--------------------------------------------------------------------------
    # new method: check_file
    #--------------------------------------------------------------------------
    def check_file(type)
    filename = "Graphics/Overlay/"
    filename += YSA::oVERLAY::GROUND if type == "ground"
    filename += YSA::oVERLAY::LIGHT if type == "light"
    filename += YSA::oVERLAY::SHADOW if type == "shadow"
    filename += YSA::oVERLAY::pARALLAX if type == "par"
    filename += $game_map.map_id.to_s
    filename += "-" + $game_variables[YSA::oVERLAY::GROUND_VARIABLE].to_s if type == "ground"
    filename += "-" + $game_variables[YSA::oVERLAY::LIGHT_VARIABLE].to_s if type == "light"
    filename += "-" + $game_variables[YSA::oVERLAY::SHADOW_VARIABLE].to_s if type == "shadow"
    filename += "-" + $game_variables[YSA::oVERLAY::pARALLAX_VARIABLE].to_s if type == "par"
    filename += ".jpg" if type == "light" || type == "shadow"
    filename += ".png" if type == "par" || type == "ground"
    return FileTest.exist?(filename)
    end

    #--------------------------------------------------------------------------
    # new method: create_overlay_map
    #--------------------------------------------------------------------------
    def create_overlay_map
    w = Graphics.width
    h = Graphics.height
    @current_light = 0
    @current_shadow = 0
    @current_par = 0
    @current_ground = 0
    # Ground Layer
    @ground = Sprite.new(@viewport1)
    @ground.z = 1
    @ground.opacity = YSA::oVERLAY::GROUND_OPACITY
    # Light Layer
    @light_viewport = Viewport.new(0, 0, w, h)
    @light_viewport.z = 10
    @light = Sprite.new(@light_viewport)
    @light.opacity = YSA::oVERLAY::LIGHT_OPACITY
    @light.blend_type = 1
    # Shadow Layer
    @shadow_viewport = Viewport.new(0, 0, w, h)
    @shadow_viewport.z = 9
    @shadow = Sprite.new(@shadow_viewport)
    @shadow.opacity = YSA::oVERLAY::SHADOW_OPACITY
    @shadow.blend_type = 2
    # Parallax Layer
    @par_viewport = Viewport.new(0, 0, w, h)
    @par_viewport.z = 8
    @par = Sprite.new(@par_viewport)
    @par.opacity = YSA::oVERLAY::pARALLAX_OPACITY
    end

    #--------------------------------------------------------------------------
    # alias method: dispose_parallax
    #--------------------------------------------------------------------------
    alias overlay_dispose_parallax dispose_parallax
    def dispose_parallax
    overlay_dispose_parallax
    dispose_overlay_map
    end

    #--------------------------------------------------------------------------
    # new method: dispose_overlay_map
    #--------------------------------------------------------------------------
    def dispose_overlay_map
    @ground.dispose
    @shadow_viewport.dispose
    @light_viewport.dispose
    @light.dispose
    @shadow.dispose
    @par_viewport.dispose
    @par.dispose
    end

    #--------------------------------------------------------------------------
    # alias method: update_parallax
    #--------------------------------------------------------------------------
    alias overlay_update_parallax update_parallax
    def update_parallax
    overlay_update_parallax
    # Parallax
    if @ground != nil
    if check_file("ground")
    @ground.visible = $game_switches[YSA::oVERLAY::GROUND_SWITCH] if @ground.visible != $game_switches[YSA::oVERLAY::GROUND_SWITCH]
    @ground.ox = $game_map.display_x * 32 if @ground.ox != $game_map.display_x * 32
    @ground.oy = $game_map.display_y * 32 if @ground.oy != $game_map.display_y * 32
    @ground.tone = $game_map.screen.tone
    if @current_ground != $game_variables[YSA::oVERLAY::GROUND_VARIABLE]
    filename = YSA::oVERLAY::GROUND
    filename += $game_map.map_id.to_s
    filename += "-" + $game_variables[YSA::oVERLAY::GROUND_VARIABLE].to_s
    @ground.bitmap = Cache.overlay(filename)
    @current_ground = $game_variables[YSA::oVERLAY::GROUND_VARIABLE]
    end
    else
    @ground.visible = false
    end
    end
    # Light
    if @light != nil && @light_viewport != nil
    if check_file("light")
    @light.visible = $game_switches[YSA::oVERLAY::LIGHT_SWITCH] if @light.visible != $game_switches[YSA::oVERLAY::LIGHT_SWITCH]
    @light.ox = $game_map.display_x * 32 if @light.ox != $game_map.display_x * 32
    @light.oy = $game_map.display_y * 32 if @light.oy != $game_map.display_y * 32
    @light.tone = $game_map.screen.tone
    @light_viewport.ox = $game_map.screen.shake
    @light_viewport.color = $game_map.screen.flash_color
    if @current_light != $game_variables[YSA::oVERLAY::LIGHT_VARIABLE]
    filename = YSA::oVERLAY::LIGHT
    filename += $game_map.map_id.to_s
    filename += "-" + $game_variables[YSA::oVERLAY::LIGHT_VARIABLE].to_s
    @light.bitmap = Cache.overlay(filename)
    @current_light = $game_variables[YSA::oVERLAY::LIGHT_VARIABLE]
    end
    else
    @light.visible = false
    end
    end
    # Shadow
    if @shadow != nil && @shadow_viewport != nil
    if check_file("shadow")
    @shadow.visible = $game_switches[YSA::oVERLAY::SHADOW_SWITCH] if @shadow.visible != $game_switches[YSA::oVERLAY::SHADOW_SWITCH]
    @shadow.ox = $game_map.display_x * 32 if @shadow.ox != $game_map.display_x * 32
    @shadow.oy = $game_map.display_y * 32 if @shadow.oy != $game_map.display_y * 32
    @shadow.tone = $game_map.screen.tone
    @shadow_viewport.ox = $game_map.screen.shake
    @shadow_viewport.color = $game_map.screen.flash_color
    if @current_shadow != $game_variables[YSA::oVERLAY::SHADOW_VARIABLE]
    filename = YSA::oVERLAY::SHADOW
    filename += $game_map.map_id.to_s
    filename += "-" + $game_variables[YSA::oVERLAY::SHADOW_VARIABLE].to_s
    @shadow.bitmap = Cache.overlay(filename)
    @current_shadow = $game_variables[YSA::oVERLAY::SHADOW_VARIABLE]
    end
    else
    @shadow.visible = false
    end
    end
    # Parallax
    if @par != nil && @par_viewport != nil
    if check_file("par")
    @par.visible = $game_switches[YSA::oVERLAY::pARALLAX_SWITCH] if @par.visible != $game_switches[YSA::oVERLAY::pARALLAX_SWITCH]
    @par.ox = $game_map.display_x * 32 if @par.ox != $game_map.display_x * 32
    @par.oy = $game_map.display_y * 32 if @par.oy != $game_map.display_y * 32
    @par.tone = $game_map.screen.tone
    @par_viewport.ox = $game_map.screen.shake
    @par_viewport.color = $game_map.screen.flash_color
    if @current_par != $game_variables[YSA::oVERLAY::pARALLAX_VARIABLE]
    filename = YSA::oVERLAY::pARALLAX
    filename += $game_map.map_id.to_s
    filename += "-" + $game_variables[YSA::oVERLAY::pARALLAX_VARIABLE].to_s
    @par.bitmap = Cache.overlay(filename)
    @current_par = $game_variables[YSA::oVERLAY::pARALLAX_VARIABLE]
    end
    else
    @par.visible = false
    end
    end
    end

    end # Spriteset_Map

    #==============================================================================
    # ■ Scene_Map
    #==============================================================================

    class Scene_Map < Scene_Base

    #--------------------------------------------------------------------------
    # alias method: post_transfer
    #--------------------------------------------------------------------------
    alias overlay_post_transfer post_transfer
    def post_transfer
    @spriteset.dispose_overlay_map
    @spriteset.create_overlay_map
    @spriteset.update
    overlay_post_transfer
    end

    end # Scene_Map

    #==============================================================================
    #
    # ▼ End of File
    #
    #==============================================================================
     
    Ok now lets get inot this step by step.
     
    1.Start a new project with defualt map size 

    Spoiler
     

    2.Fill with any green grass

     

    Spoiler
     

    3.Install Tsukihimes map Screenshot script,start the game via playtest and take a screenshot of the map(see instructions inside the script).

     

    Spoiler
     

    4.Drag and drop your map into an image editor (i'll be using GIMP for this tutorial).

     

    Spoiler
     

    5.Setup your grid (32 x 32 pixels,any color that suits you).

     

    Spoiler
     

    6.Add some parallax trees into your project as a new layer (i'll put the ones i'm using in the spoiler tag with the screenshot)

     

    Spoiler


     

    7.Draw a selection around the biggest tree,copy and paste it as a new layer.Name this layer "par Layer".

     

    Spoiler
     

    8.Hide every other layer beside and single tree

     

    Spoiler
     

    9.Now,install Yamis overlay script and create a folder in the graphics folder of your project named "Overlay".Go back into your editor and export just the tree and name it "par1-1" and place it in the new "Overlay" folder you just made.

     

    Spoiler
     

    10.Now,start your game up in the test and you should see your tree on map 1 and as expected the tree is completely above the player

     

    Spoiler
     

    .You can walk completely under it,and if you know how layers work you know that the only other layer below par is ground but if we set it up as a ground then we would be able to walk over it as if it were grass so normally your only option is to set up the passability on the roots so the player cannot interact with any part of the tree except the leaves but not only does this not feel right to keep the player that far away from the tree,it also limits how it interacts with the player and its place on the map.Now! lets do something cool to fix this and make the tree more dynamic.

     

    11.Go back into your image editor project and make the mapshot visible (so its just the mapshot and the single tree with visibility).

     

    Zoom in and Select the whole shadow in front of the tree and as much as the tree stump as possible without selecting any of the leaves!

     

    Spoiler
     

    Also,notice how the front roots are place on the grid.Its done in a way that anticipates what the player will be touching when they walk towards it.They will be standing on the roots while in front of the stump without their head touching any part of the leaves.

     

    12.Once you have your selection like the picture above.

     

    1.Copy it

    2.Cut it

    3.Paste it as a new layer and name that layer "ground layer".

     

    Spoiler
     

    move the new layer under the "par" layer (the tree).Now what we have is two images that make one image,two parts of the tree that make the whole tree.

     

    13.Now hide everything except the "par" layer (which should now have its trunk cut off) and export it and name it "par1-1" and place it in your projects overlay folder (replace the one that was in their),then,go back into the image editor and hide everything except the "ground" layer (which should be just the tree trunk and the shadow) and export it and name it "ground1-1" and place it in your projects overlay folder.

     

    Spoiler




     

     
     

    14.Now start your game via test and Viola!

     

    Spoiler


     

     

    What you now have is a tree with roots you can walk on,a tree trunk you can face and leaves you can walk under!

     

    NOTE: You will need to place invisible impassibility tiles above the characters head in the two screenshots above and you will have a perfect tree that actually behaves like a tree.

     

    Spoiler
     

    In the above pic he is standing on a root while the leaves are over his head.
  2. Thanks for this awesome tutorial :)
  3. the trees are freely available commercially ?