Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Shadow Script V.4

Here comes the 4th version of my shadow script !

It has been partially rewritten, based on your feedback. New features, bug fixes, and more to come.

New Features :

*Longer shadows if far from the source. Can be laggy, though (but you cant toggle them off) :

http://rataime.free.fr/rmxp/Demos/shadow-size.jpg[/IMG]

*Better shadows facing in the right direction, especially visible with asymetric characters.

* New configuration options : don't like the way the comments are set ? Well, you can set them the way you want (don't forget to read the comments inside the script)

http://rataime.free.fr/rmxp/Demos/shadow-setup.jpg[/IMG]

*Bug fixes, less lag, and the usual stuff. Ah, and compatible with the SDK (just remove the 2 lines if you don't use it).

Here's the demo, and here's the script :

#==============================================================================
# ** Dynamic Shadows
#------------------------------------------------------------------------------
# Rataime
# Version 4.0
# 06/05/2007 (2007-05-06)
# Version 1.0 was based on Genzai Kawakami's shadows, extra features Boushy
#==============================================================================

#==============================================================================
# Here's the brand new free configuration feature
# The comments will be compared to the pattern using Regexp, except that I did
# the entire work for you, so you don't have to know regexps at all.
# Just choose the trigger ('s', 'begin shadow' or whatever), and the pattern
# The pattern can be one line or a list to use multiple comment lines.
# arg1 is the minimum angle
# arg2 is the maximum angle
# arg3 is the maximum distance
# The only thing you must do is using 'trigger' before the arguments
# Examples :
#
# SHADOWS_SOURCE_COMMENT_TRIGGER = 's'
# SHADOWS_SOURCE_COMMENT_PATTERN = ['trigger','arg1','arg2','arg3']
# SHADOWS_CHAR_COMMENT_TRIGGER = 'o'
# SHADOWS_CHAR_COMMENT_PATTERN = 'trigger'
# is the old way to use shadows, with a single 's' in the first line, and the
# arguments in following lines
#
# SHADOWS_SOURCE_COMMENT_TRIGGER = 'begin shadow source'
# SHADOWS_SOURCE_COMMENT_PATTERN =
# ['trigger','anglemin arg1','anglemax arg2','distancemax arg3']
# SHADOWS_CHAR_COMMENT_TRIGGER = 'begin shadow'
# SHADOWS_CHAR_COMMENT_PATTERN = 'trigger'
# will work with :
# Comment "begin shadow source"
# Comment "anglemin 0"
# Comment "anglemax 0"
# Comment "distancemax 250"
#
# Take the time to choose something you like, and something compatible with other
# scripts.
# Note that the comments will be detected even if they aren't in the beginning
# of the event's action list. Ah, and you can switch the arguments if you like
#==============================================================================

#==============================================================================
# Here is the method I like best, because of its compatibility with other
# scripts. But don't hesitate to change it.
# It will react to something like Shadow|0|0|250
#==============================================================================

SHADOWS_SOURCE_COMMENT_TRIGGER = 'Shadow'
SHADOWS_SOURCE_COMMENT_PATTERN = 'trigger|arg1|arg2|arg3'
SHADOWS_CHAR_COMMENT_TRIGGER = 'o'
SHADOWS_CHAR_COMMENT_PATTERN = 'trigger'

#==============================================================================
# An important option : if you set it to true, the shadows will get longer if
# you are far from the source. Nice, but induces lag : it will eat your CPU,
# and quite possibly your first born if you try that on a big map.
#==============================================================================

SHADOW_GETS_LONGER = true

#==============================================================================
# Misc options
# If an event has its opacity below SHADOWS_OPACITY_THRESHOLD, no shadow will
# be displayed.
# Set SHADOWS_CATERPILLAR_COMPATIBLE to true if you uses the caterpillar script
#==============================================================================

SHADOWS_OPACITY_THRESHOLD = 254
SHADOWS_CATERPILLAR_COMPATIBLE = true

#==============================================================================
# You probably won't need to touch this : it's the 'map' of how to display the
# shadow depending on the event's direction and his relative position to the
# source. a minus means the shadow is mirrored. It seems complex, and it is.
# Complain to Enterbrain (why didn't they use something clockwise or counter-
# clockwise ? I suspect it's because of the rm2k legacy. More explanations
# below.
#==============================================================================

SHADOWS_DIRECTION_ARRAY = Array.new
SHADOWS_DIRECTION_ARRAY[2] = [ -3, 4, -2, 1 ]
SHADOWS_DIRECTION_ARRAY[4] = [ 4, -2, 1, -3 ]
SHADOWS_DIRECTION_ARRAY[6] = [ 1, -3, 4, -2 ]
SHADOWS_DIRECTION_ARRAY[8] = [ -2, 1, -3, 4 ]

#------------------------------------------------------------------------------
# * SDK Log Script and Check requirements
#------------------------------------------------------------------------------
SDK.log('Shadows', 'rataime', 1.00, '05.06.2007')
SDK.check_requirements(2, [1,2])

#==============================================================================
# ** Game_Party, for compatibility with the caterpillar script.
#==============================================================================

class Game_Party
attr_reader :characters
end

#==============================================================================
# ** Sprite_Shadow, the meat of this script
#==============================================================================

class Sprite_Shadow < RPG::Sprite

attr_accessor :character

#--------------------------------------------------------------------------
# * Initialize
#--------------------------------------------------------------------------
def initialize(viewport, character = nil,source = nil,anglemin=0, \
anglemax=0,distancemax=700)
super(viewport)
@anglemin=anglemin.to_f
@anglemax=anglemax.to_f
@distancemax=distancemax.to_f
@character = character
@source = source
self.color = Color.new(0, 0, 0)
update
end

#--------------------------------------------------------------------------
# * Update
#--------------------------------------------------------------------------
def update
if @character.transparent or @character.opacity <= SHADOWS_OPACITY_THRESHOLD
self.visible = false
return
end
@deltax=(@source.real_x-@character.real_x)/4
@deltay= (@source.real_y-@character.real_y)/4
@distance = (((@deltax ** 2) + (@deltay ** 2))** 0.5)
if @distancemax !=0 and @distance>@distancemax
self.visible = false
return
end
self.angle = 57.3*Math.atan2(@deltax, @deltay )
@angle_trigo= (self.angle+90) % 360
if @anglemin !=0 or @anglemax !=0
if (@angle_trigo<@anglemin or @angle_trigo>@anglemax) and \
@anglemin<@anglemax
self.visible = false
return
elsif (@angle_trigo<@anglemin and @angle_trigo>@anglemax) and \
@anglemin>@anglemax
self.visible = false
return
end
end
super
if @tile_id != @character.tile_id or
@character_name != @character.character_name or
@character_hue != @character.character_hue
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_hue = @character.character_hue
if @tile_id >= 384
self.bitmap = RPG::Cache.tile($game_map.tileset_name,
@tile_id, @character.character_hue)
self.src_rect.set(0, 0, 32, 32)
self.ox = 16
self.oy = 32
else
self.bitmap = RPG::Cache.character(@character.character_name,
@character.character_hue)
@cw = bitmap.width / 4
@ch = bitmap.height / 4
self.ox = @cw / 2
self.oy = @ch
end
end
self.visible = true
self.x = @character.screen_x
self.y = @character.screen_y-8
self.z = @character.screen_z(@ch)-1
if @character.animation_id != 0
animation = $data_animations[@character.animation_id]
animation(animation, true)
@character.animation_id = 0
end
if @tile_id == 0
sx = @character.pattern * @cw
quarter = ((@angle_trigo/90+0.5).floor)%4
# The quarter is the position of the event relative to the source.
# Imagine the source is the o point (0,0). Trace the 2 lines
# y=x and y=-x : you get something like a big X
# On the right, quarter=0. Up, quarter = 1, and so on
# Take the @character.direction row (2,4,6,8), and the quarter
# column (0,1,2,3) (remember, it starts at 0), and you'll get
# a number between 1 and 4. It correspond to the row of the charset
# the shadow will be, and mirrored if negative.
# Yes, it isn't obvious, but I didn't find any simple operation to
# get those.
magic = SHADOWS_DIRECTION_ARRAY[@character.direction][quarter]
magic = -magic
if magic < 0
self.mirror = true
magic = -magic
else
self.mirror = false
end
sy = (magic-1)*@ch
self.src_rect.set(sx, sy, @cw, @ch)
end
# This is the formula of the opacity in function of the distance
# ** 2 means square
self.opacity = 1200/((@distance ** 2)/ 1000 + 6)
# This is the formula of the size in function of the distance
# The 0.75 is here so you have a size of 1:1 when next to the source.
self.zoom_y=0.75 + @distance / 256 if SHADOW_GETS_LONGER
end

end

#======================================================================
# ** Sprite_Character EDIT
#======================================================================
# All those things could go somewhere else, but they
# work quite well here.
#======================================================================

class Sprite_Character < RPG::Sprite

@@regexp_source = nil
@@regexp_source_short = nil
@@regexp_char = nil
@@regexp_char_short = nil

alias rataime_shadow_initialize initialize

#--------------------------------------------------------------------------
# * Initialize
#--------------------------------------------------------------------------
def initialize(viewport, character = nil)

if @@regexp_source == nil
regexp_initialize
end
@character = character
super(viewport)
@ombrelist=[]
if (character.is_a?(Game_Event) and character.list!=nil)
# Let's check the comments in our event list
for j_list in 0..character.list.size-1
#p [@@regexp_source_short, character.list[j_list].parameters[0]]
if (character.list[j_list].code == 108 and \
@@regexp_source_short.match(character.list[j_list].parameters[0])!= nil)
# Haha ! We found a trigger tag ! Time to retrieve the parameters !
parameter_string = character.list[j_list].parameters[0]
j_list += 1
while j_list < character.list.size and \
(character.list[j_list].code == 108 or \
character.list[j_list].code == 408)
parameter_string = parameter_string + "\n" + \
character.list[j_list].parameters[0]
j_list += 1
end
# The following line is a nifty piece of code. Really.
@anglemin,@anglemax,@distancemax = \
(regexp_get_parameters(parameter_string, true)+[nil]*3)[0..2]
# We have our source parameters. Let's find which events we should
# make have a shadow
for i in $game_map.events.keys.sort
if ($game_map.events.is_a?(Game_Event) and \
$game_map.events.list!=nil)
for i_list in 0..$game_map.events.list.size-1
if (($game_map.events.list[i_list].code == 108 or \
$game_map.events.list[i_list].code == 408 )and \
@@regexp_char_short.match( \
$game_map.events.list[i_list].parameters[0])!= nil)
@ombrelist[i+1] = Sprite_Shadow.new(viewport, $game_map.events,\
self,@anglemin,@anglemax,@distancemax)
break # no need to add more than one shadow per source per event
end
end # end for
end
end # end for
@ombrelist[1] = Sprite_Shadow.new(viewport, $game_player,self,@anglemin,\
@anglemax,@distancemax)
#===================================================
# Compatibility with fukuyama's caterpillar script
#===================================================
if SHADOWS_CATERPILLAR_COMPATIBLE and $game_party.characters!=nil

for member in $game_party.characters
@ombrelist.push(Sprite_Shadow.new(viewport, member,self,@anglemin,\
@anglemax,@distancemax))
end

end
#===================================================
# End of the compatibility
#===================================================
end
break # We don't need to go further in the source's list
end # end for
end
rataime_shadow_initialize(viewport, @character)
end

alias rataime_shadow_update update
#--------------------------------------------------------------------------
# * Update
#--------------------------------------------------------------------------
def update
rataime_shadow_update
if @ombrelist!=[]
for i in 1..@ombrelist.size
if @ombrelist!=nil
@ombrelist.update
end
end
end
end

#--------------------------------------------------------------------------
# * Real_x : it just returns the character's real_x
#--------------------------------------------------------------------------
def real_x
return @character.real_x
end

#--------------------------------------------------------------------------
# * Real_y : it just returns the character's real_y
#--------------------------------------------------------------------------
def real_y
return @character.real_y
end

#--------------------------------------------------------------------------
# * regexp_initialize : the brand new configuration function
# This function generate the regexps based on the configuration
#--------------------------------------------------------------------------
def regexp_initialize
@@regexp_source = regexp_generate(true)
@@regexp_char = regexp_generate(false)
@@regexp_source_short = @@regexp_source
@@regexp_char_short = @@regexp_char
if SHADOWS_SOURCE_COMMENT_PATTERN.is_a?(Array)
@@regexp_source_short = regexp_generate_short(@@regexp_source)
end
if SHADOWS_CHAR_COMMENT_PATTERN.is_a?(Array)
@@regexp_char_short = regexp_generate_short(@@regexp_char)
end
end
#--------------------------------------------------------------------------
# * regexp_generate generate a full length regexp including the arguments
# detection.
#--------------------------------------------------------------------------
def regexp_generate(source = false)
if source
pattern = SHADOWS_SOURCE_COMMENT_PATTERN
trigger = SHADOWS_SOURCE_COMMENT_TRIGGER
@@argument_indexes_source = []
indexes = @@argument_indexes_source
else
pattern = SHADOWS_CHAR_COMMENT_PATTERN
trigger = SHADOWS_CHAR_COMMENT_TRIGGER
@@argument_indexes_char = []
indexes = @@argument_indexes_char
end
if pattern.is_a?(Array)
string = Regexp.escape(pattern.join("\n"))
else
string = Regexp.escape(pattern)
end
string = string.gsub('trigger',')('+trigger+')(')
splitted = string.split('arg')
regexp = '\A(' + splitted[0] + '(\d+)){0,1}'
for i in 1..splitted.size-1
if splitted[0..0].to_i == 0
p 'Error : You probably forgot a digit after an arg'
raise
else
indexes.push(splitted[0..0].to_i)
regexp = regexp + '(' + splitted[1..splitted.size-1] + '(\d+)){0,1}'
end
end
return Regexp.new(regexp.chomp('(\d+)){0,1}') + ')')
end
#--------------------------------------------------------------------------
# * Will return a shorter regexp, but still able to identify the trigger
#--------------------------------------------------------------------------
def regexp_generate_short(regexp)
string = regexp.inspect
string = string.split('\n')[0]
string = string[1..string.size-2]
return Regexp.new(string)
end
#--------------------------------------------------------------------------
# * regexp_get_parameters is called whenever a trigger has been identify,
# and the script wants to know the arguments. It returns an array in the
# right orger [arg1,arg2,arg3]
#--------------------------------------------------------------------------
def regexp_get_parameters(string, source = false)
if source
regexp = @@regexp_source
indexes = @@argument_indexes_source.dup
else
regexp = @@regexp_char
indexes = @@argument_indexes_char.dup
end
indexes = indexes.reverse!
match_array = regexp.match(string).captures
return_array = Array.new
if match_array.size > 3
for i in 2..match_array.size-1
if ((i.to_f/2).ceil)*2 != i and match_array!=nil
return_array[indexes.pop-1] = match_array
end
end
end
return return_array
end

end


Quick instructions (thank to EiB)

The script is easily adapted with simple event comments.

To create a shadow source:
Create an event over an object that gives light. Then type in the comment corresponding to your SHADOW_SOURCE_COMMENT style of commenting.

By default, it's "Shadow|arg1|arg2|arg3"

Now you can use the following items to perfect the shadow source:
arg1(minimum angle) and arg2(maximum angle): Replace arg with an angular value. The angles follow the Polar Coordinate Grid, in degrees. If you are unsure about how to work the angles according to the Polar Coordinate Grid, please Google it.
arg3(distance): Replace n with the a number to justify the radius of the shadows effect. The larger the number, the father you can be from the source and still achieve a shadow.
By default, you'll have something like "Shadow|0|180|230" (please read the instructions inside the script)

When a source is created it automatically applied to your actor (hero).

Adding shadows to events:
Here is how to add shadows to events. Warning this works best with bipedal chatacters, not well with animals and objects.

Just place a comment saying (by default):o.

There you go! :p

Many thanks to busbuzz and Firestalker5, my efficient and devoted beta-testers, and to Thales for being a smartass.

Well, now, enjoy !
 

Ludzix

Member

Could you allow for using a different graphic for shadow, for example "Fighter01" for character and "Fighter01_s" for his shadow?
 

Korin

Member

Welcome back!

Personally, I prefer the old way because of its quickness. However, I can see how it may conflict with other methods! Perhaps the third option?
 
I think you should comment them with a new way. Like for shadow distance and angles.

Comment: Shadow Begin, 180, 360, etc. I look forward to seeing the new shadow, reflection script.
 
Um can you make it so you can use them without the SDK? Cause most of my scripts so far don't use the SDK and the SDK pretty much screws up all of my scripts.

But yes I think the comments for each option should go like shadow, angle, distance, so on.
And the trigger comments should be user settable in the script. So like you can set it to start shadow or shadow. It would be very useful.
 
Toushi Katou;196060 said:
Um can you make it so you can use them without the SDK? Cause most of my scripts so far don't use the SDK and the SDK pretty much screws up all of my scripts.

It would not be hard to make such an incompattible version, yet is the question, will a non-SDK version work with your scripts?
 
I don't SDK [much] and all my scripts work fine.

SDK is a sound idea in thought, but fails [IMHO] when implemented. Most of the scripts I have found don't work if you have SDK in your project and I have yet to find SDK Scripts that do what my other scripts do.

I realize that the there is a thread to ask for a conversion to SDK, but why should I ask for a conversion [and wait for someone to agree to do said conversion and then wait even longer for that person to write the conversion] when I have the script I need in front of me.

Now with SDK 2.2 out there is no compatability with non-SDK scripts. I have placed the SDK in my project and I had to delete just about every script I had in order to stop all the errors I was getting. I have managed to make my game using non-SDk scripts [I have one SDK script I think and I use SDK 1.5 heavy deleted]. I have deleted the lines that check for SDK and the scripts work fine, but the scripts that were made for SDK 2.2 use a completely script base. They use the SDK 2.2 for their information, this bypasses the main scripts in the RGSS [essentially making the SDK the RGSS main scripts]. Which means the writer of the script forces the user to use SDK 2.2 completely eliminating compatability with other scripts that don't use the SDK.

This is from experience, I am not a scripter [not Ruby anyway]. I have my opinions about SDK based off my observation of what it has done with my own project.

Now that I am done hijacking the Thread:
-----------------------------------------------------------

I feel a good change to script would be to make it customizable. Make it so you can change the color of the shadow and maybe how long the shadow will be.

Other than that, the script is great the way it is.
 
Well, to be fair, SDK usually fails when the script was badly coded (no aliases, etc). A well coded non-SDK script would work fine with the SDK, and a SDK-only script would work better with other SDK scripts.

Anyway, I'm starting to like the whole "Configure the comments the way you like" idea !
 
I use some KGC scripts, CCOA scripts, and some other scritps I picked up along the way. They all play nice with each other [a few issues if you reorder them in the list, but easily fixed].

They don't however play nice with SDK. When I did finally have to place SDK in to my project I had to delete all but the parts that the script needed to read in order for my other scripts to work right.

Like I said before my opinions are based on observations of the SDK in my own project. I have a very limited knowledge of Ruby and I can only make minor changes.

I hate to hijack your thread [and now that I think back I can't for the life of me remember what set me off on this rant].

Just to give the impression that I'm on topic of the thread: I really think your script is great the way it is.
 
Ok. The reason SDK breaks my scripts is cause my scripts overwrite the standard classes but when I implement the SDK it overrides my scripts.
I just want two versions one SDK for those who do use the SDK but one without SDK in it so those who don't use it can. Now don't get me wrong the SDK is great! But it is not needed for my game which I started production before the SDK was made.

Also one more suggestion to the shadow script! Ok my biggest pet peeve about it is that the shadow would appear on things it wasn't supposed to and made stuff look unrealistic. So maybe like it shows up on certain tiles... like choose a tile terrain. But you can set the different terrains it uses so like it can have multiple.
 
I don't like the SDK as well, so making this SDK would be a bad idea in my humble opinion. SDK seems to work with all the other SDK scripts and have no errors, but not with other scripts. Even if the script is perfectly coded, their is still many incompatibilities. And the sole fact that some of the battle systems I like don't work with the SDK, is enough to make me not want to use it. So, if you do intend to make this SDK, have a backup with a non SDK version.

Now as for the reflection script, I don't like the idea of having to change the terrain tag of it all the time so maybe another method could be employed to make the reflection work. I think just adding a comment to where you want the reflection to appear should be sufficient enough. Anywhere without the comment, the reflection would not appear.
 
Ok, I'm posting here to remind everyone that this isn't a discussion on "Why I hate SDK" any further posts that are trying to bring the posts here away from the topic at hand shall be deleted and the user will be warned for spamming. Thank you.
 
I have a suggestion... When doing the shadows you should have something like:
Shadow_g meaning that the shadow starts directly under the character and circles around, and then Shadow_a for aerial, meaning like airships, dragons, flying creatures don't look stupid and instead have a drop shadow instead of a shadow stuck to their tails etc. One more thing, when a sprite has an opacity less than 255 it should remove the shadow... otherwise you can see invisible sprites cause of the shadow, if someone wants that it should be an optional thing like SSO<255 standing for Show Shadow if Opacity is > or less than 255.

One suggestion with the reflection script, is there anyway to make the reflection start where the water comes up and drifts back so it isn't on the land that isn't wet.
 
Axerax;196490 said:
One suggestion with the reflection script, is there anyway to make the reflection start where the water comes up and drifts back so it isn't on the land that isn't wet.

There is one : as there's no way to "guess" where the water starts and the ground ends, you have to add on a higher level the same(s) tile(s), but with the water removed. See my demo for an example.
 
Hey Rataime, when do you think the new versionof the shadow/reflection script will be out?

I also have another suggestion... can you make it less laggy? I was using your most recent version and I have three light sources. It causes my game to lag like never before. Can you fix that?
 
Trickster;196451 said:
Ok, I'm posting here to remind everyone that this isn't a discussion on "Why I hate SDK" any further posts that are trying to bring the posts here away from the topic at hand shall be deleted and the user will be warned for spamming. Thank you.

Well I wasn't trying to bring the discussion away from the topic. I was simply making a suggestion that there should be two versions. I was also stating reasons as to why he should do it. But I understand, so I will stop now...

One more suggestion is that when you like use jumping scripts it would be awsome as the player got higher in the air the shadow got smaller.

Thanks!
 
Already planned ^^

Here is my list up to now :

Update Issue 0000003 block assigned (rataime) 04-25-07 New configuration
Update Issue 0000007 block assigned (rataime) 04-25-07 Exact shadow
Update Issue 0000010 minor assigned (rataime) 04-25-07 Shadows of transparent characters
Update Issue 0000009 feature assigned (rataime) 04-25-07 Jump and aerial
Update Issue 0000002 feature assigned (rataime) 04-25-07 Different graphic for shadow
Update Issue 0000008 feature assigned (rataime) 04-25-07 Shadow length
Update Issue 0000006 feature assigned (rataime) 04-25-07 Disappear on some terrains
Update Issue 0000005 feature assigned (rataime) 04-25-07 Change color
Update Issue 0000004 feature assigned (rataime) 04-25-07 SDK compatibility
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top