Well, this is not really a script for the public, but it is something I've been working on for a while.
This is just one of many modules that I am creating to speed up the creation of battle systems and other complex systems. The main idea behind them is to be able to add a lot of functions to a class like movement or effects.
I wanted to create DLL for this, but my knowledge in that are vague at best at the moment. Also something I wanted to ask is if it is possible to inject a module into a class without having to modify said class.
For example instead of going to each class and doing "include module_name", just do it with an external call like "inject_module_to_class(class_name, module_name)".
And here is the script, this is just the movement part of the script, other effects such as jumping are ready but I am not satisfied with the math.
#==============================================================================
# ** TDS Module
# Version: 1.0
#------------------------------------------------------------------------------
#
#==============================================================================
# * Import to Global Hash *
#==============================================================================
($imported ||= {})[:TDS_Module] = true
module TDS
end
module TDS
#============================================================================
# ** Movement - (Movement Addon)
# Version: 1.0
#----------------------------------------------------------------------------
# This Module handles object movement.
#============================================================================
module Movement
#--------------------------------------------------------------------------
# * Constants (Structs)
#--------------------------------------------------------------------------
# Battle Action Base
Move_Object = Struct.new(:real_x, :real_y, :x, :y, :x_speed, :y_speed)
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize(*atts)
super(*atts)
# Initialize Moving Objects Hash
clear_moving_objects
end
#--------------------------------------------------------------------------
# * Clear All Moving Objects
#--------------------------------------------------------------------------
def clear_moving_objects ; @moving_objects = {} end
#--------------------------------------------------------------------------
# * Determine if Object can be moved
#--------------------------------------------------------------------------
def can_move?(obj) ; obj.is_a?(Window) or obj.is_a?(Sprite) end
#--------------------------------------------------------------------------
# * Determine if object is moving
#--------------------------------------------------------------------------
def moving_object?(obj)
# Return false if Moving Objects Hash does not include
return false if !@moving_objects.has_key?(obj)
# Get Moving Object Destination Properties
dest = @moving_objects[obj]
# If Object Real X & Y is not equal to Destination X & Y
return (dest.real_x != dest.x or dest.real_y != dest.y)
end
#--------------------------------------------------------------------------
# * Remove Moving Object
#--------------------------------------------------------------------------
def remove_moving_object(obj) ; @moving_objects.delete(obj) end
#--------------------------------------------------------------------------
# * Finish Object Movement (Instant Move)
#--------------------------------------------------------------------------
def finish_object_movement(obj)
# Return if Moving Objects hash does not include object
return if !@moving_objects.has_key?(obj)
# Get Moving Object Destination Properties & Set Object X and Y Positions
dest = @moving_objects[obj] ; obj.x = dest.real_x = dest.x ; obj.y = dest.real_y = dest.y
end
#--------------------------------------------------------------------------
# * Object Initialization
# speed : movement speed [X, Y] (Array or Integer (Set both speeds))
#--------------------------------------------------------------------------
def move_obj_to(obj, x, y, speed, appr = false)
# Return if Object cannot be moved
return if !can_move?(obj)
# Create Speed Array for X & Y Speeds if it's a single integer
speed = [speed, speed] if speed.is_a?(Numeric)
# Destination Properties
dest = Move_Object.new(obj.x, obj.y, x, y, speed.at(0), speed.at(1))
# If Approximation flag is true
if appr
# Set Destination Approximated X & Y Speed Speed
dest.x_speed = (obj.x - x).abs.to_f / speed.at(0) ; dest.y_speed = (obj.y - y).abs.to_f / speed.at(1)
end
# Set Moving Objects Destination Properties
@moving_objects[obj] = dest
# Finish Object Movement if Speed is 0
finish_object_movement(obj) if speed.reduce(:+) == 0
end
#--------------------------------------------------------------------------
# * Move Object towards coordinates
# x : x amout to move towards
# y : y amount to move towards
# dur : movement duration
# appr : if false duration is treated as speed
#--------------------------------------------------------------------------
def move_obj_towards(obj, x, y, dur, appr = true)
# Move To Coordinates
move_obj_to(obj, obj.x + x, obj.y + y, dur, appr)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update(*args, &block)
# Update Super if Defined
super(*args, &block) if defined?(super)
# Update Moving Objects
@moving_objects.each {|obj, dest| update_moving_objects(obj, dest)}
end
#--------------------------------------------------------------------------
# * Update Moving Objects
# obj : moving object
# dest : destination properties
#--------------------------------------------------------------------------
def update_moving_objects(obj, dest)
# Return if Destination Properties are not for Object Movement
return if !dest.is_a?(Move_Object)
# Left & Right Movement
obj.x = dest.real_x = [dest.real_x - dest.x_speed, dest.x].max if dest.x < dest.real_x
obj.x = dest.real_x = [dest.real_x + dest.x_speed, dest.x].min if dest.x > dest.real_x
# Up & Down Movement
obj.y = dest.real_y = [dest.real_y - dest.y_speed, dest.y].max if dest.y < dest.real_y
obj.y = dest.real_y = [dest.real_y + dest.y_speed, dest.y].min if dest.y > dest.real_y
# Remove Moving Object if it's not moving anymore
remove_moving_object(obj) if !moving_object?(obj)
end
end
end
module TDS
#============================================================================
# ** Movement - (Movement Addon)
# Version: 1.0
#----------------------------------------------------------------------------
# This Module handles object movement.
#============================================================================
module Movement
#--------------------------------------------------------------------------
# * Determine if moving
#--------------------------------------------------------------------------
def moving? ; moving_object?(self) end
#--------------------------------------------------------------------------
# * Move to Coordinates
#--------------------------------------------------------------------------
def move_to(x, y, speed, appr = false) ; move_obj_to(self, x, y, speed, appr) end
#--------------------------------------------------------------------------
# * Finish Movement (Instant Move)
#--------------------------------------------------------------------------
def finish_movement ; finish_object_movement(self) end
end
end
And here is an example that can tested with any game, just go to any menu and press the CTRL key.
#==============================================================================
# ** Scene_Base
#------------------------------------------------------------------------------
# This is a super class of all scenes within the game.
#==============================================================================
class Scene_Base
#--------------------------------------------------------------------------
# * Included Modules
#--------------------------------------------------------------------------
include TDS::Movement
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
update_basic
# If Input Trigger CTRL
if Input.trigger?(:CTRL)
instance_variables.each do |varname|
ivar = instance_variable_get(varname)
# If Instance Variable is a window or sprite
if ivar.is_a?(Window) or ivar.is_a?(Sprite)
x = rand(Graphics.width - ivar.width)
y = rand(Graphics.height - ivar.height)
move_obj_to(ivar, x, y, 15 + rand(15), true)
end
end
end
end
end
Here is another example, this one is to display the use of the module within a class like a window instead of the whole scene like the one above.
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
# This class performs the menu screen processing.
#==============================================================================
Window_Base.send(:include, TDS::Movement)
class Scene_Menu < Scene_MenuBase
#--------------------------------------------------------------------------
# * Post-Start Processing
#--------------------------------------------------------------------------
def post_start
# Move Windows outside of screen
@command_window.move_to(-@command_window.width, @command_window.y, 0)
@gold_window.move_to(-@gold_window.width, @gold_window.y, 0)
@status_window.move_to(Graphics.width + @status_window.width, @status_window.y, 0)
# Deactivate Command Window
@command_window.deactivate
super
# Move Windows into screen
@command_window.move_to(0, 0, 15, true)
@gold_window.move_to(0, @gold_window.y, 15, true)
@status_window.move_to(@command_window.width, @status_window.y, 15, true)
# Get Windows
windows = [@command_window, @gold_window, @status_window]
# While Windows are Moving
while windows.any? {|w| w.moving?}
# Update Basic Components
update_basic
# Go Through Basic Input (Cancel/Confirm)
[:C, :B].each {|input|
# Finish Window Movement If Input Trigger
windows.each {|w| w.finish_movement} if Input.trigger?(input)
}
end
# Activate Command Window
@command_window.activate
end
end