じ☆ve冰风 发表于 2026-7-22 21:19:02

Sprite Reflections and Wave Effects

This is one of the first scripts I made back in 2012.

Back in the early era of XP, JmsPlDnl y Rataime made a Sprite Reflection script for that maker, and it was widely used. I took that idea to make another one, but in another way. In my version, each event and player has a copy of its graphic, flipped and with a Z below 0. That means usually you don't see it, but if you define a transparent water autotile and use a panorama or a similar trick to define the background of the water, you can see the reflection in between.

Author: Wecoc
Release Date: July 2012
Last Version: January 2018

Terms of Use
- Giving credits (Wecoc) for using this script is optional, but appreciated.
- The Wave Effect Addon is an edit of a code by Zecomeia, so you should credit her.
- You can repost this code.
- You can edit this code freely, and distribute the edits as well.
- This code can be used on commercial games.

Code
                Ruby:       
#==============================================================================
# ** Sprite_Reflection v1.2
#------------------------------------------------------------------------------
# Author: Wecoc (no credits required)
#==============================================================================

#==============================================================================
# ** Sprite_Reflection
#==============================================================================

class Sprite_Reflection < RPG::Sprite
#--------------------------------------------------------------------------
attr_accessor :character
#--------------------------------------------------------------------------
# * Initialize
#--------------------------------------------------------------------------
def initialize(viewport=nil, character=nil)
    super(viewport)
    @character = character
    update
end
#--------------------------------------------------------------------------
# * Update
#--------------------------------------------------------------------------
def update
    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 = (not @character.transparent && @character.reflection)
    self.mirror = true
    self.angle = 180
    if @tile_id == 0
      sx = @character.pattern * @cw
      sy = (@character.direction - 2) / 2 * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
    self.x = @character.screen_x - 1
    self.y = @character.screen_y
    self.z = @character.screen_z(@ch) - 999
    self.opacity = @character.opacity
    self.blend_type = @character.blend_type
    self.bush_depth = @character.bush_depth
end
end

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

class Game_Character
#--------------------------------------------------------------------------
# * Initialize
#--------------------------------------------------------------------------
attr_accessor :reflection
alias reflect_ini initialize unless $@
def initialize
    reflect_ini
    @reflection = true
end
end

#==============================================================================
# ** Spriteset_Map
#==============================================================================

class Spriteset_Map
#--------------------------------------------------------------------------
# * Initialize
#--------------------------------------------------------------------------
alias reflect_ini initialize unless $@
def initialize
    @reflection_sprites = []
    reflect_ini
    for i in 0...@character_sprites.size
      s = @character_sprites
      sprite = Sprite_Reflection.new(@viewport1, s.character)
      @reflection_sprites.push(sprite)
    end
    update
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
alias reflect_dis dispose unless $@
def dispose
    reflect_dis
    for sprite in @reflection_sprites
      sprite.dispose
    end
end
#--------------------------------------------------------------------------
# * Update
#--------------------------------------------------------------------------
alias reflect_upd update unless $@
def update
    reflect_upd
    for sprite in @reflection_sprites
      sprite.update
    end
end
end


Usage
To define if the player or an event has reflection, simply use this on a script call:
                Code:       
$game_player.reflection = true / false
$game_map.events.reflection = true / false


Related scripts
By the same time, Zecomeia made a code for Wave Effects.

Long time ago I made some edits of that code, I'll include it here with some instructions as well.

Spoiler: Wave Effects                Ruby:       
#==============================================================================
# ** Wave Effect
#------------------------------------------------------------------------------
# By:         Zecomeia
# Date:       01/03/2010
# Version:    1.0
# Edit by:    Wecoc
# Edit Date:26/07/2017
#------------------------------------------------------------------------------
# www.colmeia-do-ze.blogspot.com
#==============================================================================

class Sprite

attr_accessor   :wave_amp
attr_accessor   :wave_length
attr_accessor   :wave_speed
attr_accessor   :wave_phase
attr_accessor   :temp_bitmap

alias wave_effect_ini initialize unless $@
def initialize(viewport=nil)
    @wave_amp = 0
    @wave_length = 72
    @wave_speed = 720
    @wave_phase = 0.25
    wave_effect_ini(viewport)
    @temp_bitmap = nil
end

alias wave_effect_upd update unless $@
def update
    # the wave effect only works if wave_amp
    # propertie is a number more than zero
    wave_effect if @wave_amp > 0
    wave_effect_upd
end

# Return the width of image, because when use
# obj.bitmap.width the value will be more than
# the original value(because effect)
def width
    return (self.bitmap.width - @wave_amp * 2)
end

def wave_effect
    return if self.bitmap.nil?
    @temp_bitmap = self.bitmap if @temp_bitmap.nil?
    cw = @temp_bitmap.width + (@wave_amp * 2)
    ch = @temp_bitmap.height
    # Follow the VX wave effect, each horizontal line
    # has 8 pixel of height. This device provides less
    # lag in game.
    divisions = @temp_bitmap.height / 8
    divisions += 1 if @temp_bitmap.height % 8 != 0
    self.bitmap = Bitmap.new(cw, ch)
    for i in 0..divisions
      x = @wave_amp * Math.sin(i * 2 * Math::PI / (@wave_length / 8).to_i +
      (@wave_phase * Math::PI) / 180.0)
      src_rect = Rect.new(0, i*8, @temp_bitmap.width, 8)
      dest_rect = Rect.new(@wave_amp + x, i * 8, @temp_bitmap.width, 8)
      self.bitmap.stretch_blt(dest_rect, @temp_bitmap, src_rect)
    end
    # frame rate: VX = 60 | XP = 40
    # wave speed compatibility VX to XP: wave_speed * 60/40
    # then: wave_speed * 1.5
    @wave_phase += @wave_speed * 1.5 / @wave_length
    @wave_phase -= 360 if @wave_phase > 360
    @wave_phase += 360 if @wave_phase < 0
end
end

for Klass in
class Klass
    attr_accessor   :wave_amp
    attr_accessor   :wave_length
    attr_accessor   :wave_speed
    alias wave_effect_ini initialize unless $@
    def initialize(*args)
      wave_effect_ini(*args)
      @wave_amp = 0
      @wave_length = 72
      @wave_speed = 720
    end
end
end

class Spriteset_Map
alias wave_effect_upd update unless $@
def update
    wave_effect_upd
    for i in 0...@character_sprites.size
      sprite = @character_sprites
      if i == @character_sprites.size - 1
      sprite.wave_amp   = $game_player.wave_amp
      sprite.wave_length= $game_player.wave_length
      sprite.wave_speed   = $game_player.wave_speed
      else
      event = $game_map.events
      next if event.nil?
      sprite.wave_amp   = event.wave_amp
      sprite.wave_length= event.wave_length
      sprite.wave_speed   = event.wave_speed
      end
    end
    for i in 0...@picture_sprites.size
      picture = $game_screen.pictures
      sprite = @picture_sprites
      sprite.wave_amp   = picture.wave_amp
      sprite.wave_length= picture.wave_length
      sprite.wave_speed   = picture.wave_speed
    end
end
end

class Spriteset_Battle
alias wave_effect_upd update unless $@
def update
    wave_effect_upd
    for i in 0...@enemy_sprites.size
      enemy = $game_troop.enemies.reverse
      next if enemy.nil? or !enemy.exist?
      sprite = @enemy_sprites
      sprite.wave_amp   = enemy.wave_amp
      sprite.wave_length= enemy.wave_length
      sprite.wave_speed   = enemy.wave_speed
    end
    for i in 0...@actor_sprites.size
      actor = $game_party.actors
      next if actor.nil? or !actor.exist?
      sprite = @actor_sprites
      sprite.wave_amp   = actor.wave_amp
      sprite.wave_length= actor.wave_length
      sprite.wave_speed   = actor.wave_speed
    end
    for i in 0...@picture_sprites.size
      picture = $game_screen.pictures
      sprite = @picture_sprites
      sprite.wave_amp   = picture.wave_amp
      sprite.wave_length= picture.wave_length
      sprite.wave_speed   = picture.wave_speed
    end
end
end


To use it you should use sprite.wave_amp = n, where the n is the desired amplitude and the sprite may be:

                Code:       
$game_player            # The player
$game_map.events      # Event
$game_screen.pictures # Picture
$game_party.actors    # Battler (Actor, by party ID)
$game_actors          # Battler (Actor, by actor ID)
$game_troop.enemies   # Battler (Enemy, by troop ID)


Finally, this little AddOn uses both scripts to implement the wave effect on the reflections.

Spoiler: Sprite Reflection's Wave AddOn                Ruby:       
#==============================================================================
# ** Sprite Reflection's Wave AddOn
#------------------------------------------------------------------------------
# This code uses Sprite_Reflection 1.2 and Wave Effect
#==============================================================================

class Sprite_Reflection
#----------------------------------------------------------------------------
DEFAULT_WAVE_AMP = 2
DEFAULT_WAVE_LENGTH = 128
DEFAULT_WAVE_SPEED = 720
#----------------------------------------------------------------------------
alias wave_addon_ini initialize unless $@
def initialize(*args)
    wave_addon_ini(*args)
    @wave_amp = DEFAULT_WAVE_AMP
    @wave_length = DEFAULT_WAVE_LENGTH
    @wave_speed = DEFAULT_WAVE_SPEED
end
end

class Sprite
def remove_wave
    @wave_amp = 0
    self.bitmap = @temp_bitmap.clone
end
end

class Scene_Map
attr_reader :spriteset
end

class Spriteset_Map
attr_reader :reflection_sprites
end

class Interpreter
def reflection_sprite(event_id)
    return if !$scene.is_a?(Scene_Map)
    spriteset = $scene.spriteset
    return if spriteset.nil?
    sprites = spriteset.reflection_sprites
    case event_id
    when -1 # Player
      sprite = sprites.select do |sprite|
      sprite.character == $game_player
      end
    when 0 # Current Character
      sprite = sprites.select do |sprite|
      sprite.character == $game_map.events[@event_id]
      end
    else # Character ID
      sprite = sprites.select do |sprite|
      sprite.character == $game_map.events
      end
    end
    return sprite
end
end


To get the sprite and apply the Wave Effect changes, use:
                Code:       
reflection_sprite(-1) # Player
reflection_sprite(0)# Current event
reflection_sprite(1)# Event with ID 1


For example:
reflection_sprite(-1).wave_amp = 4

If you want to remove the effect, setting the wave_amp to 0 is not enough since the current waves will still be visible.
To completely remove it use:
reflection_sprite(-1).remove_wave
That's all.


本贴来自国际rpgmaker官方论坛作者:Wecoc处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/sprite-reflections-and-wave-effects.138188/
页: [1]
查看完整版本: Sprite Reflections and Wave Effects