8 dic 2012

[Códigos] Perspectiva en Sprites (RPG Maker XP)


Hola amigos,
es momento de inaugurar una nueva sección. Esta vez toca la sección de Códigos, de MATERIALES.

Para esta ocasión, he rescatado un script algo antiguo. El primero que hice público. Si estás familiarizado con el RPGMXP, es probable que conozcas el "famoso" SDK. Bueno pues esto es una des-SDKlización de uno de los scripts de SephirothSpawn.


Perspectiva en Sprites

Autores: Boyuna-sama (autor del original SehirothSpawn)
(SDK Module VR original por SephirothSpawn & Near Fantastica)
Versión: 1.1
Tipo: Sistema de modificación de Sprite
Término clave: Añadido de Entorno

Introducción


Éste script ha sido diseñado para manipular los sprites de los eventos 
(mas conocidos como charsets) para aparecer con perspectiva.
Actualización - Añadido un modulo que previene un error con Drct_Regions.
Rect_Regions y Circ_Regions ahora funcionan correctamente.
Este trabajo está protegido por la siguiente licencia (en ingles, lo siento):

Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported( http://creativecommons.org/licenses/by-nc-sa/3.0/ )You are free:
  1. to Share - to copy, distribute and transmit the work
  2. 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.

Características

Puedes definir regiones de perspectiva, para que así, cuando un evento esté en un
punto específico, tendrá alterado su punto de perspectiva y escalado.


Imágenes

Imágenes:




Demo

Aquí 

Script

Simplemente crea un nuevo script encima de Main y pega el siguiente código

Script :

#==============================================================================
# ** Perspective Sprites
#------------------------------------------------------------------------------
# Original author: SephirothSpawn
# Non-SDK version: Boyuna-sama
# Version 1.1
# 2010-06-11
#------------------------------------------------------------------------------
# * Version History :
#
#   Version 1 ---------------------------------------------------- (2010-01-20)
#   Version 1.1 -------------------------------------------------- (2010-06-11)
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# * Description :
#
#   This script was designed to manipulate event sprites to appear with
#   perspective. You can define perspective points on the map and scaling for
#   each perspective point. You may also define perspective regions, so when
#   an event is : at a specific point ; within a defined rectangle ; within a
#   defined circle, they will have altered perspective points and scaling.
#
#   How it works:
#
#   The events will zoom the distance they are from the defined perspective
#   point divided by the scale. If the focus point is 400 pixels away and
#   the scale is 800, the zoom will be 400 / 800. So the sprite will be
#   half of it's original size.
#------------------------------------------------------------------------------
# * Instructions :
#
#   Place above Main.
#   To define focus points, scales and regions, refer to Customization.
#   To get the current zoom of an event, refer to Syntax.
#------------------------------------------------------------------------------
# * Customization :
#
#   Focus Points
#    - Focus_Points = { map_id => [real_x, real_y], ... }
#
#   Scaling
#    - Scaling      = { map_id => n, ... }
#
#   Regions alter the focus points & scaling for characters in these regions
#
#   Direct Region (Specific Point)
#    - Drct_Regions = {
#        map_id => { [x, y] => [real_x, real_y, scaling], ...},
#        ...
#      }
#   Regions (Rectangular)
#    - Rect_Regions = {
#        map_id => { [x, y, w, h] => [real_x, real_y, scaling], ... },
#        ...
#      }
#
#   Regions (Circular)
#    - Circ_Regions = {
#        map_id => { [x, y, r] => [real_x, real_y, scaling], ... },
#        ...
#      }
#------------------------------------------------------------------------------
# * Syntax :
#
#   Getting Curren Zoom of character (Returns Float)
#    - <game_character>.zoom?
#==============================================================================

#==============================================================================
# Module Required to work properly
# View Range
# No-SDK version by Boyuna-sama
# Original version by SephirothSpawn & Near Fantastica
#==============================================================================

module VR
  #----------------------------------------------------------------------------
  # * Within Range Test
  #----------------------------------------------------------------------------
  def VR.in_range?(*args)
    # If 3 Arguments (Element, Object, Range)
    if args.size == 3
      x = (args[0].x - args[1].x) ** 2
      y = (args[0].y - args[1].y) ** 2
      r = args[2]
    # If 5 Arguments (Elementx, Elementy, Objectx, Objecty, Range)
    elsif args.size == 5
      x = (args[0] - args[2]) ** 2
      y = (args[1] - args[3]) ** 2
      r = args[4]
    else
      p 'Wrong Defined Number of Arguments'
      return
    end
    return (x + y) <= (r * r)
  end
  #----------------------------------------------------------------------------
  # * Within Rect Range Test
  #----------------------------------------------------------------------------
  def VR.in_rect_range?(*args)
    # If 2 Arguments (Object, Rect)
    if args.size == 2
      x_, y_ = args[0].x, args[0].y
      x, y, w, h = args[1].x, args[1].y, args[1].width, args[1].height
    # If 3 Arguments (Objectx, Objecty, Rect)
    elsif args.size == 3
      x_, y_ = args[0], args[1]
      x, y, w, h = args[2].x, args[2].y, args[2].width, args[2].height
    # If 5 Arguments (Object, Rectx, Recty, Rectwidth, Rectheight)
    elsif args.size == 5
      x_, y_ = args[0].x, args[0].y
      x, y, w, h = args[1], args[2], args[3], args[4]
    # If 6 Arguments (Objectx, Objecty, Rectx, Recty, Rectwidth, Rectheight)
    elsif args.size == 6
      x_, y_, x, y, w, h = *args
    else
      p 'Wrong Defined Number of Arguments'
      return
    end
    # Return Object Within Rect
    return x_.between?(x, x + w) && y_.between?(y, y + h)
  end
  #----------------------------------------------------------------------------
  # * Range
  #----------------------------------------------------------------------------
  def VR.range(*args)
    # If 2 Arguments (Element, Object)
    if args.size == 2
      x = (args[0].x - args[1].x) * (args[0].x - args[1].x)
      y = (args[0].y - args[1].y) * (args[0].y - args[1].y)
      integer = true
    # If 3 Arguments (Element, Object, Integer
    elsif args.size == 3
      x = (args[0].x - args[1].x) * (args[0].x - args[1].x)
      y = (args[0].y - args[1].y) * (args[0].y - args[1].y)
      integer = args[2]
    # If 4 Arguments (Elementx, Elementy, Objectx, Objecty)
    elsif args.size == 4
      x = (args[0] - args[2]) * (args[0] - args[2])
      y = (args[1] - args[3]) * (args[1] - args[3])
      integer = true
    # If 5 Arguments (Elementx, Elementy, Objectx, Objecty, integer)
    elsif args.size == 5
      x = (args[0] - args[2]) * (args[0] - args[2])
      y = (args[1] - args[3]) * (args[1] - args[3])
      integer = args[4]
    else
      p 'Wrong Defined Number of Arguments'
      return
    end
    r = Math.sqrt(x + y)
    return integer ? r.to_i : r
  end
end

#==============================================================================
# ** Perspective
#==============================================================================

module Perspective
  #--------------------------------------------------------------------------
  # * Options
  #
  #  ~ Focus Points
  #     - Focus_Points = { map_id => [real_x, real_y], ... }
  #
  #  ~ Scaling
  #     - Scaling      = { map_id => n, ... }
  #
  #  Regions alter the focus points & scaling for characters in these regions
  #
  #  ~ Direct Region (Specific Point)
  #     - Drct_Regions = {
  #         map_id => { [x, y] => [real_x, real_y, scaling], ...},
  #         ...
  #       }
  #  ~ Regions (Rectangular)
  #     - Rect_Regions = {
  #         map_id => { [x, y, w, h] => [real_x, real_y, scaling], ... },
  #         ...
  #       }
  #
  #  ~ Regions (Circular)
  #     - Circ_Regions = {
  #         map_id => { [x, y, r] => [real_x, real_y, scaling], ... },
  #         ...
  #       }
  #
  #--------------------------------------------------------------------------
  Focus_Points = {
    1 => [1020, - 720]
  }
  Scaling      = {
    1 => 1600
  }
  Drct_Regions = {
    # Example
    2 => { [3, 3] => [0, 0, 200] }
  }
  Rect_Regions = {
    # Example
    2 => { [4, 4, 5, 5] => [1000, -200, 500] }
  }
  Circ_Regions = {
  }
  #--------------------------------------------------------------------------
  # * Get Focus Point
  #--------------------------------------------------------------------------
  def self.focus_point?(map_id)
    return Focus_Points.has_key?(map_id) ? Focus_Points[map_id] : nil
  end
  #--------------------------------------------------------------------------
  # * Get Scaling
  #--------------------------------------------------------------------------
  def self.scaling?(map_id)
    return Scaling.has_key?(map_id) ? Scaling[map_id] : 1
  end
  #--------------------------------------------------------------------------
  # * Direct Regions
  #--------------------------------------------------------------------------
  def self.drct_regions?(map_id)
    return Drct_Regions.has_key?(map_id) ? Drct_Regions[map_id] : {}
  end
  #--------------------------------------------------------------------------
  # * Rect Regions
  #--------------------------------------------------------------------------
  def self.rect_regions?(map_id)
    return Rect_Regions.has_key?(map_id) ? Rect_Regions[map_id] : {}
  end
  #--------------------------------------------------------------------------
  # * Circ Regions
  #--------------------------------------------------------------------------
  def self.circ_regions?(map_id)
    return Circ_Regions.has_key?(map_id) ? Circ_Regions[map_id] : {}
  end
  #--------------------------------------------------------------------------
  # * Focus & Scale at Point
  #--------------------------------------------------------------------------
  def self.focus_and_scale?(map_id, x, y)
    # Sets Key
    key = [map_id, x, y]
    # If Search Contains Key
    if @searches.has_key?(key)
      # Returns Saved Data
      return @searches[key]
    end
    # Checks Direct Locations
    self.drct_regions?(map_id).each do |xy, xys|
      return xys if x == xy[0] && y == xy[0]
    end
    # Checks Rect Regions
    self.rect_regions?(map_id).each do |xywh, xys|
      x_, y_ = xywh[0],      xywh[1]
      w, h = xywh[2], xywh[3]
      return xys if VR.in_rect_range?(x, y, x_, y_, w, h)
    end
    # Checks Circular Regions
    self.circ_regions?(map_id).each do |xyr, xys|
      return xys if VR.in_range?(x, y, xyr[0], xyr[1], xyr[2])
    end
    # Save & Return Map Scaling
    f, s = self.focus_point?(map_id), self.scaling?(map_id)
    return (f.nil? ? [nil, nil, 1] : [f[0], f[1], s])
  end
  #--------------------------------------------------------------------------
  # * Get Searches (DO NOT ALTER)
  #--------------------------------------------------------------------------
  # Create Search Data
  @searches = {}
  # Load Map Data
  load_data('Data/MapInfos.rxdata').keys.each do |map_id|
    # Get Map Data
    map = load_data(sprintf('Data/Map%03d.rxdata', map_id))
    # Pass Through Map Dimensions
    for x in 0...map.width
      for y in 0...map.height
        # Save Map Scale
        @searches[[map_id, x, y]] = self.focus_and_scale?(map_id, x, y)
      end
    end
  end
end

#==============================================================================
# ** Game_Map
#==============================================================================

class Game_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :p_focus_point
  attr_reader :p_scaling
  attr_reader :p_drct_regs
  attr_reader :p_rect_regs
  attr_reader :p_circ_regs
  #--------------------------------------------------------------------------
  # * Setup
  #--------------------------------------------------------------------------
  alias setup_later_xlaw setup
  def setup(map_id)
    setup_later_xlaw(map_id)
    # Sets Perspective Properties
    @p_focus_point = Perspective.focus_point?(@map_id)
    @p_scaling     = Perspective.scaling?(@map_id)
    @p_drct_regs   = Perspective.drct_regions?(@map_id)
    @p_rect_regs   = Perspective.rect_regions?(@map_id)
    @p_circ_regs   = Perspective.circ_regions?(@map_id)
  end
  #--------------------------------------------------------------------------
  # * Focus and Scale?
  #--------------------------------------------------------------------------
  def focus_and_scale?(x, y)
    return Perspective.focus_and_scale?(@map_id, x, y)
  end
end

#==============================================================================
# ** Game_Character
#==============================================================================

class Game_Character
  #--------------------------------------------------------------------------
  # * Perspective Zoom?
  #--------------------------------------------------------------------------
  def perspective_zoom?
    # Gets Focus Points
    f_x, f_y, scale = $game_map.focus_and_scale?(@x, @y)
    # Calculates X & Y Difference
    x_diff = (@real_x / 4 - f_x).abs
    y_diff = (@real_y / 4 - f_y).abs
    # Calculates Distance From Focus
    distance = Math.sqrt(x_diff ** 2 + y_diff ** 2)
    # Returns Zoom
    return distance / scale.to_f
  end
end

#==============================================================================
# ** Sprite_Character
#==============================================================================

class Sprite_Character
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias seph_spritepersp_schr_update update
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Original Update
    seph_spritepersp_schr_update
    # Unless No Focus Point
    unless $game_map.p_focus_point.nil?
      # If Visible
      if self.visible
        # Sets Zoom
        zoom = @character.perspective_zoom?
        self.zoom_x = zoom
        self.zoom_y = zoom
      end
    end
  end
end



Instrucciones

Dentro del script.


Compatibilidad

Puede causar incompatibilidad con otros sistema relacionados con los sprites.
Ponlo debajo de cualquier otro script que sobrescriba Game_Map (el
método setup) y/o Sprite_Character (el método update).


Créditos y Agradecimientos

* SephirothSpawn (versión original para el SDK)
* Near Fantastica (Module VR co-creador)
* Boyuna-sama (versión No-SDK)
* Seraphim Falling (Por reportarme un bug)

Notas Finales

Si encuentras algún bug por favor, comunícamelo por aquí
Gracias^^

2 comentarios:

  1. Que interesante esta nueva seccion, es una verdadera lastima el no poder comprender bien del todo algunos terminos, pero poder leer las caracteristicas de un script y luego ver lo complejo que queda al final una vez creado, es como digo, muy interesante.

    Una seccion que completa mas aun este estupendo blog, cada vez mas y mas contenido variado, genial chicos ^^.

    ResponderEliminar
  2. Gracias. La verdad es que es algo que teníamos por aquí rondando, que programé en su momento, así que nos dijimos "¿porque no hacerlos públicos?" Y aquí está xD. Aun a pesar, de no poder entender algunos términos, incluimos una demo para poder ver que hace exactamente el script. Te recomiendo bajarla, pues no requiere la instalación de nada adicional. Lo bajas, descomprimes y pruebas.

    ResponderEliminar

Thanks for commenting. We value your opinion.
Gracias por comentar. Tu opinión nos importa.