[XP] Perspective Sprites

Started by X-Law, January 19, 2010, 08:15:01 pm

Previous topic - Next topic

X-Law

January 19, 2010, 08:15:01 pm Last Edit: June 10, 2010, 07:50:46 pm by X-Law
Perspective Sprites
Authors: X-Law (original author SehirothSpawn)
                                    (original SDK Module VR by SephirothSpawn & Near Fantastica)

Version: 1.1
Type: Sprite Modifier System
Key Term: Environment Add-on



Introduction

This script was designed to manipulate event sprites to appear with perspective.
Update - Added a missing module that prevent an error with Drct_Regions, Rect_Regions and Circ_Regions. Now works correctly.

This work is protected by the following license:
QuoteCreative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
( 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.



Features

   * You can 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.


Screenshots
Spoiler: ShowHide





Demo

Not necessary, i think :P


Script

Just make a new script above main and paste this code into it.
Spoiler: ShowHide
#==============================================================================
# ** Perspective Sprites
#------------------------------------------------------------------------------
# Original author: SephirothSpawn
# Non-SDK version: X-Law
# 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 X-Law
# 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



Instructions

Inside the script in the first comment.


Compatibility

Maybe can cause incompatibility with any other related sprite system. Put it below any script that overwrite Game Map (method "setup") and/or Sprite character (method "update")


Credits and Thanks

   * SephirothSpawn (original version for SDK)
   * Near Fantastica (Module VR co-creator)
   * X-Law (Non-SDK version)
   * Seraphim Falling (for reporting that bug to me =D)


Author's Notes

This is my first try to contribute to this community. I'm not a pro scripter, but i'm trying my best to learn. So if you find any bugs, please report them here.
Thanks ^^

AlbatrosStorm is on sale now!

Calintz


X-Law


AlbatrosStorm is on sale now!

Calintz

Does this script put the map in perspective also, because if it didn't things would look odd.. .. ..
O can this script be used for other areas of the game?

Fantasist

January 20, 2010, 02:48:03 am #4 Last Edit: January 20, 2010, 02:49:15 am by Fantasist
@Cal: Hey buddy :) , been long, hasn't it? Using perspective on maps is what Mode7 is, so no. And if I remember correctly, as far as things that stick out of the ground are events and not part of the mapping, it won't look that odd.

@X-Law: While you're at it, you might want to remove hashes from the configs and use Blizz's trick ;)

EDIT:
Also, I'm curious. Was the license attached to the original script or are you using it now?
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Blizzard

Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

X-Law

@Calintz
As Fantasist said this is only for sprites (so main characters and events only). This is intended to use in combination with 3D-based panoramas for your maps

@Fantasist
use Blizz's trick? oh? can you explain it more to me?  :o

About the license, well, you know, the original author was Seph so the original license is the sdk one. I just grabbed the script from his testbed (in that testbed i can't remember any license of use :/). I'm using it now cuz i think it's a nice license type :)

@Blizzard
Sorry i didn't realized that this post exists :(. I edited mine it's now correct?

AlbatrosStorm is on sale now!

Jalm

Yay, someone finally got around to non-SDKing this thing. Now if only I could remember what I wanted to use the original script for.

Regardless, great job. *level*

Holyrapid

This seems to be something in the alley of Ccoa's over world sprites (though, i think that it only scales the sprites) Nice work, i guess. Good job at de-SDKing the scrript, because SDK is a mess...

X-Law

Thanks :). I think de-SDKing scripts is too easy compared to making new scripts lol. (So don't hesitate to ask me for a "conversion" of some SDK-scripts)

AlbatrosStorm is on sale now!

X-Law

updated to 1.1
*Fixing a problem with some functions
:)

AlbatrosStorm is on sale now!