#=============================================================================== # #=============================================================================== module Graphics @@transition = nil STOP_WHILE_TRANSITION = true unless defined?(transition_KGC_SpecialTransition) class << Graphics alias transition_KGC_SpecialTransition transition end class << Graphics alias update_KGC_SpecialTransition update end end # duration is in 1/20ths of a second def self.transition(duration = 8, filename = "", vague = 20) duration = duration.floor if judge_special_transition(duration, filename) duration = 0 filename = "" end duration *= Graphics.frame_rate / 20 # For default fade-in animation begin transition_KGC_SpecialTransition(duration, filename, vague) rescue Exception transition_KGC_SpecialTransition(duration, "", vague) if filename != "" end if STOP_WHILE_TRANSITION && !@_interrupt_transition while @@transition && !@@transition.disposed? update end end end def self.update update_KGC_SpecialTransition @@transition.update if @@transition && !@@transition.disposed? @@transition = nil if @@transition&.disposed? end def self.judge_special_transition(duration, filename) return false if @_interrupt_transition ret = true if @@transition && !@@transition.disposed? @@transition.dispose @@transition = nil end duration /= 20.0 # Turn into seconds dc = File.basename(filename).downcase case dc # Other coded transitions when "breakingglass" then @@transition = Transitions::BreakingGlass.new(duration) when "rotatingpieces" then @@transition = Transitions::ShrinkingPieces.new(duration, true) when "shrinkingpieces" then @@transition = Transitions::ShrinkingPieces.new(duration, false) when "splash" then @@transition = Transitions::SplashTransition.new(duration, 9.6) when "random_stripe_v" then @@transition = Transitions::RandomStripeTransition.new(duration, 0) when "random_stripe_h" then @@transition = Transitions::RandomStripeTransition.new(duration, 1) when "zoomin" then @@transition = Transitions::ZoomInTransition.new(duration) when "scrolldown" then @@transition = Transitions::ScrollScreen.new(duration, 2) when "scrollleft" then @@transition = Transitions::ScrollScreen.new(duration, 4) when "scrollright" then @@transition = Transitions::ScrollScreen.new(duration, 6) when "scrollup" then @@transition = Transitions::ScrollScreen.new(duration, 8) when "scrolldownleft" then @@transition = Transitions::ScrollScreen.new(duration, 1) when "scrolldownright" then @@transition = Transitions::ScrollScreen.new(duration, 3) when "scrollupleft" then @@transition = Transitions::ScrollScreen.new(duration, 7) when "scrollupright" then @@transition = Transitions::ScrollScreen.new(duration, 9) when "mosaic" then @@transition = Transitions::MosaicTransition.new(duration) # HGSS transitions when "snakesquares" then @@transition = Transitions::SnakeSquares.new(duration) when "diagonalbubbletl" then @@transition = Transitions::DiagonalBubble.new(duration, 0) when "diagonalbubbletr" then @@transition = Transitions::DiagonalBubble.new(duration, 1) when "diagonalbubblebl" then @@transition = Transitions::DiagonalBubble.new(duration, 2) when "diagonalbubblebr" then @@transition = Transitions::DiagonalBubble.new(duration, 3) when "risingsplash" then @@transition = Transitions::RisingSplash.new(duration) when "twoballpass" then @@transition = Transitions::TwoBallPass.new(duration) when "spinballsplit" then @@transition = Transitions::SpinBallSplit.new(duration) when "threeballdown" then @@transition = Transitions::ThreeBallDown.new(duration) when "balldown" then @@transition = Transitions::BallDown.new(duration) when "wavythreeballup" then @@transition = Transitions::WavyThreeBallUp.new(duration) when "wavyspinball" then @@transition = Transitions::WavySpinBall.new(duration) when "fourballburst" then @@transition = Transitions::FourBallBurst.new(duration) when "vstrainer" then @@transition = Transitions::VSTrainer.new(duration) when "vselitefour" then @@transition = Transitions::VSEliteFour.new(duration) when "rocketgrunt" then @@transition = Transitions::RocketGrunt.new(duration) when "vsrocketadmin" then @@transition = Transitions::VSRocketAdmin.new(duration) # Graphic transitions when "fadetoblack" then @@transition = Transitions::FadeToBlack.new(duration) when "fadefromblack" then @@transition = Transitions::FadeFromBlack.new(duration) else ret = false end Graphics.frame_reset if ret return ret end end #=============================================================================== # Screen transition animation classes. #=============================================================================== module Transitions #============================================================================= # A base class that all other screen transition animations inherit from. #============================================================================= class Transition_Base DURATION = nil def initialize(duration, *args) @disposed = false if duration <= 0 @disposed = true return end @duration = self.class::DURATION || duration @parameters = args @timer = 0.0 @overworld_bitmap = $game_temp.background_bitmap initialize_bitmaps return if disposed? @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 @sprites = [] @overworld_sprite = new_sprite(0, 0, @overworld_bitmap) @overworld_sprite.z = -1 initialize_sprites @timings = [] set_up_timings end def new_sprite(x, y, bitmap, ox = 0, oy = 0) s = Sprite.new(@viewport) s.x = x s.y = y s.ox = ox s.oy = oy s.bitmap = bitmap return s end def dispose return if disposed? dispose_all @sprites.each { |s| s&.dispose } @sprites.clear @overworld_sprite.dispose @overworld_bitmap&.dispose @viewport&.dispose @disposed = true end def disposed?; return @disposed; end def update return if disposed? @timer += Graphics.delta_s if @timer >= @duration dispose return end update_anim end def initialize_bitmaps; end def initialize_sprites; end def set_up_timings; end def dispose_all; end def update_anim; end end #============================================================================= # #============================================================================= class BreakingGlass < Transition_Base NUM_SPRITES_X = 8 NUM_SPRITES_Y = 6 def initialize_sprites @overworld_sprite.visible = false # Overworld sprites sprite_width = @overworld_bitmap.width / NUM_SPRITES_X sprite_height = @overworld_bitmap.height / NUM_SPRITES_Y NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @sprites[idx_sprite] = new_sprite(i * sprite_width, j * sprite_height, @overworld_bitmap) @sprites[idx_sprite].src_rect.set(i * sprite_width, j * sprite_height, sprite_width, sprite_height) end end end def set_up_timings @start_y = [] NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @start_y[idx_sprite] = @sprites[idx_sprite].y @timings[idx_sprite] = 0.5 + rand end end end def update_anim proportion = @timer / @duration @sprites.each_with_index do |sprite, i| sprite.y = @start_y[i] + (Graphics.height * @timings[i] * proportion * proportion) sprite.opacity = 255 * (1 - proportion) end end end #============================================================================= # #============================================================================= class ShrinkingPieces < Transition_Base NUM_SPRITES_X = 8 NUM_SPRITES_Y = 6 def initialize_sprites @overworld_sprite.visible = false # Overworld sprites sprite_width = @overworld_bitmap.width / NUM_SPRITES_X sprite_height = @overworld_bitmap.height / NUM_SPRITES_Y NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @sprites[idx_sprite] = new_sprite((i + 0.5) * sprite_width, (j + 0.5) * sprite_height, @overworld_bitmap, sprite_width / 2, sprite_height / 2) @sprites[idx_sprite].src_rect.set(i * sprite_width, j * sprite_height, sprite_width, sprite_height) end end end def update_anim proportion = @timer / @duration @sprites.each_with_index do |sprite, i| sprite.zoom_x = (1 - proportion).to_f sprite.zoom_y = sprite.zoom_x if @parameters[0] # Rotation direction = (1 - (2 * (((i / NUM_SPRITES_X) + (i % NUM_SPRITES_X)) % 2))) sprite.angle = direction * 360 * 2 * proportion end end end end #============================================================================= # #============================================================================= class SplashTransition < Transition_Base NUM_SPRITES_X = 16 NUM_SPRITES_Y = 12 SPEED = 40 def initialize_sprites @overworld_sprite.visible = false # Black background @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.black) # Overworld sprites sprite_width = @overworld_bitmap.width / NUM_SPRITES_X sprite_height = @overworld_bitmap.height / NUM_SPRITES_Y NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @sprites[idx_sprite] = new_sprite((i + 0.5) * sprite_width, (j + 0.5) * sprite_height, @overworld_bitmap, sprite_width / 2, sprite_height / 2) @sprites[idx_sprite].src_rect.set(i * sprite_width, j * sprite_height, sprite_width, sprite_height) end end end def set_up_timings @start_positions = [] @move_vectors = [] vague = (@parameters[0] || 9.6) * SPEED NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i spr = @sprites[idx_sprite] @start_positions[idx_sprite] = [spr.x, spr.y] dx = spr.x - (Graphics.width / 2) dy = spr.y - (Graphics.height / 2) move_x = move_y = 0 if dx == 0 && dy == 0 move_x = (dx == 0) ? rand_sign * vague : dx * SPEED * 1.5 move_y = (dy == 0) ? rand_sign * vague : dy * SPEED * 1.5 else radius = Math.sqrt((dx**2) + (dy**2)) move_x = dx * vague / radius move_y = dy * vague / radius end move_x += (rand - 0.5) * vague move_y += (rand - 0.5) * vague @move_vectors[idx_sprite] = [move_x, move_y] end end end def update_anim proportion = @timer / @duration @sprites.each_with_index do |sprite, i| sprite.x = @start_positions[i][0] + (@move_vectors[i][0] * proportion) sprite.y = @start_positions[i][1] + (@move_vectors[i][1] * proportion) sprite.opacity = 384 * (1 - proportion) end end #--------------------------------------------------------------------------- private def rand_sign return (rand(2) == 0) ? 1 : -1 end end #============================================================================= # #============================================================================= class RandomStripeTransition < Transition_Base STRIPE_WIDTH = 2 def initialize_sprites @overworld_sprite.visible = false # Overworld sprites if @parameters[0] == 0 # Vertical stripes sprite_width = STRIPE_WIDTH sprite_height = @overworld_bitmap.height num_stripes_x = @overworld_bitmap.width / STRIPE_WIDTH num_stripes_y = 1 else # Horizontal stripes sprite_width = @overworld_bitmap.width sprite_height = STRIPE_WIDTH num_stripes_x = 1 num_stripes_y = @overworld_bitmap.height / STRIPE_WIDTH end num_stripes_y.times do |j| num_stripes_x.times do |i| idx_sprite = (j * num_stripes_x) + i @sprites[idx_sprite] = new_sprite(i * sprite_width, j * sprite_height, @overworld_bitmap) @sprites[idx_sprite].src_rect.set(i * sprite_width, j * sprite_height, sprite_width, sprite_height) end end end def set_up_timings @sprites.length.times do |i| @timings[i] = @duration * i / @sprites.length end @timings.shuffle! end def update_anim @sprites.each_with_index do |sprite, i| next if @timings[i] < 0 || @timer < @timings[i] sprite.visible = false @timings[i] = -1 end end end #============================================================================= # #============================================================================= class ZoomInTransition < Transition_Base def initialize_sprites @overworld_sprite.x = Graphics.width / 2 @overworld_sprite.y = Graphics.height / 2 @overworld_sprite.ox = @overworld_bitmap.width / 2 @overworld_sprite.oy = @overworld_bitmap.height / 2 end def update_anim proportion = @timer / @duration @overworld_sprite.zoom_x = 1 + (7 * proportion) @overworld_sprite.zoom_y = @overworld_sprite.zoom_x @overworld_sprite.opacity = 255 * (1 - proportion) end end #============================================================================= # #============================================================================= class ScrollScreen < Transition_Base def update_anim proportion = @timer / @duration if (@parameters[0] % 3) != 2 @overworld_sprite.x = [1, -1, 0][@parameters[0] % 3] * Graphics.width * proportion end if ((@parameters[0] - 1) / 3) != 1 @overworld_sprite.y = [1, 0, -1][(@parameters[0] - 1) / 3] * Graphics.height * proportion end end end #============================================================================= # #============================================================================= class MosaicTransition < Transition_Base MAX_PIXELLATION_FACTOR = 16 def initialize_bitmaps @buffer_original = @overworld_bitmap.clone # Copy of original, never changes @buffer_temp = @overworld_bitmap.clone # "Clipboard" holding shrunken overworld end def set_up_timings @start_black_fade = @duration * 0.8 end def dispose_all @buffer_original&.dispose @buffer_temp&.dispose end def update_anim proportion = @timer / @duration inv_proportion = 1 / (1 + (proportion * (MAX_PIXELLATION_FACTOR - 1))) new_size_rect = Rect.new(0, 0, @overworld_bitmap.width * inv_proportion, @overworld_bitmap.height * inv_proportion) # Take all of buffer_original, shrink it and put it into buffer_temp @buffer_temp.stretch_blt(new_size_rect, @buffer_original, Rect.new(0, 0, @overworld_bitmap.width, @overworld_bitmap.height)) # Take shrunken area from buffer_temp and stretch it into buffer @overworld_bitmap.stretch_blt(Rect.new(0, 0, @overworld_bitmap.width, @overworld_bitmap.height), @buffer_temp, new_size_rect) if @timer >= @start_black_fade @overworld_sprite.opacity = 255 * (1 - ((@timer - @start_black_fade) / (@duration - @start_black_fade))) end end end #============================================================================= # #============================================================================= class FadeToBlack < Transition_Base def update_anim @overworld_sprite.opacity = 255 * (1 - (@timer / @duration)) end end #============================================================================= # #============================================================================= class FadeFromBlack < Transition_Base def update_anim @overworld_sprite.opacity = 255 * @timer / @duration end end #============================================================================= # HGSS wild outdoor #============================================================================= class SnakeSquares < Transition_Base DURATION = 1.25 TIME_TO_ZOOM = 0.2 # In seconds NUM_SPRITES_X = 8 NUM_SPRITES_Y = 6 # Must be an even number TOTAL_SPRITES = NUM_SPRITES_X * NUM_SPRITES_Y def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_square") if !@black_bitmap @disposed = true return end @zoom_x_target = Graphics.width.to_f / (@black_bitmap.width * NUM_SPRITES_X) @zoom_y_target = Graphics.height.to_f / (@black_bitmap.height * NUM_SPRITES_Y) end def initialize_sprites NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i if idx_sprite >= TOTAL_SPRITES / 2 sprite_x = ((j.odd?) ? i : (NUM_SPRITES_X - i - 1)) * @black_bitmap.width else sprite_x = ((j.even?) ? i : (NUM_SPRITES_X - i - 1)) * @black_bitmap.width end sprite_x += @black_bitmap.width / 2 @sprites[idx_sprite] = new_sprite(sprite_x, j * @black_bitmap.height * @zoom_y_target, @black_bitmap, @black_bitmap.width / 2) @sprites[idx_sprite].zoom_y = @zoom_y_target @sprites[idx_sprite].visible = false end end end def set_up_timings time_between_zooms = (@duration - TIME_TO_ZOOM) * 2 / (TOTAL_SPRITES - 1) NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i idx_from_start = (idx_sprite >= TOTAL_SPRITES / 2) ? TOTAL_SPRITES - 1 - idx_sprite : idx_sprite @timings[idx_sprite] = time_between_zooms * idx_from_start end end end def dispose_all @black_bitmap.dispose end def update_anim @sprites.each_with_index do |sprite, i| next if @timings[i] < 0 || @timer < @timings[i] sprite.visible = true sprite.zoom_x = @zoom_x_target * (@timer - @timings[i]) / TIME_TO_ZOOM if sprite.zoom_x >= @zoom_x_target sprite.zoom_x = @zoom_x_target @timings[i] = -1 end end end end #============================================================================= # HGSS wild indoor day (origin=0) # HGSS wild indoor night (origin=3) # HGSS wild cave (origin=3) #============================================================================= class DiagonalBubble < Transition_Base DURATION = 1.25 TIME_TO_ZOOM = 0.2 # In seconds NUM_SPRITES_X = 8 NUM_SPRITES_Y = 6 TOTAL_SPRITES = NUM_SPRITES_X * NUM_SPRITES_Y def initialize_bitmaps @bitmap = RPG::Cache.transition("black_square") if !@bitmap @disposed = true return end @zoom_x_target = Graphics.width.to_f / (@bitmap.width * NUM_SPRITES_X) @zoom_y_target = Graphics.height.to_f / (@bitmap.height * NUM_SPRITES_Y) end def initialize_sprites NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @sprites[idx_sprite] = new_sprite(((i * @bitmap.width) + (@bitmap.width / 2)) * @zoom_x_target, ((j * @bitmap.height) + (@bitmap.height / 2)) * @zoom_y_target, @bitmap, @bitmap.width / 2, @bitmap.height / 2) @sprites[idx_sprite].visible = false end end end def set_up_timings NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_from_start = (j * NUM_SPRITES_X) + i # Top left -> bottom right case @parameters[0] # Origin when 1 # Top right -> bottom left idx_from_start = (j * NUM_SPRITES_X) + NUM_SPRITES_X - i - 1 when 2 # Bottom left -> top right idx_from_start = TOTAL_SPRITES - 1 - ((j * NUM_SPRITES_X) + NUM_SPRITES_X - i - 1) when 3 # Bottom right -> top left idx_from_start = TOTAL_SPRITES - 1 - idx_from_start end dist = i + (j.to_f * (NUM_SPRITES_X - 1) / (NUM_SPRITES_Y - 1)) @timings[idx_from_start] = (dist / ((NUM_SPRITES_X - 1) * 2)) * (@duration - TIME_TO_ZOOM) end end end def dispose_all @bitmap.dispose end def update_anim @sprites.each_with_index do |sprite, i| next if @timings[i] < 0 || @timer < @timings[i] sprite.visible = true size = (@timer - @timings[i]) / TIME_TO_ZOOM sprite.zoom_x = @zoom_x_target * size sprite.zoom_y = @zoom_y_target * size next if size < 1.0 sprite.zoom_x = @zoom_x_target sprite.zoom_y = @zoom_y_target @timings[i] = -1 end end end #============================================================================= # HGSS wild water #============================================================================= class RisingSplash < Transition_Base DURATION = 1.25 MAX_WAVE_AMPLITUDE = 6 WAVE_SPACING = Math::PI / 10 # Density of overworld waves (20 strips per wave) WAVE_SPEED = Math::PI * 10 # Speed of overworld waves going up the screen MAX_BUBBLE_AMPLITUDE = -32 BUBBLES_WAVE_SPEED = Math::PI * 2 def initialize_bitmaps @bubble_bitmap = RPG::Cache.transition("water_1") @splash_bitmap = RPG::Cache.transition("water_2") @black_bitmap = RPG::Cache.transition("black_half") dispose if !@bubble_bitmap || !@splash_bitmap || !@black_bitmap end def initialize_sprites @overworld_sprite.visible = false # Overworld strips (they go all wavy) rect = Rect.new(0, 0, Graphics.width, 2) (Graphics.height / 2).times do |i| @sprites[i] = new_sprite(0, i * 2, @overworld_bitmap) @sprites[i].z = 2 rect.y = i * 2 @sprites[i].src_rect = rect end # Bubbles @bubbles_sprite = new_sprite(0, Graphics.height, @bubble_bitmap) @bubbles_sprite.z = 3 # Water splash @splash_sprite = new_sprite(0, Graphics.height, @splash_bitmap) @splash_sprite.z = 4 # Foreground black @black_sprite = new_sprite(0, Graphics.height, @black_bitmap) @black_sprite.z = 5 @black_sprite.zoom_y = 2.0 end def set_up_timings @splash_rising_start = @duration * 0.5 @black_rising_start = @duration * 0.9 end def dispose_all # Dispose sprites @bubbles_sprite&.dispose @splash_sprite&.dispose @black_sprite&.dispose # Dispose bitmaps @bubble_bitmap&.dispose @splash_bitmap&.dispose @black_bitmap&.dispose end def update_anim # Make overworld wave strips oscillate amplitude = MAX_WAVE_AMPLITUDE * [@timer / 0.1, 1].min # Build up to max in 0.1 seconds @sprites.each_with_index do |sprite, i| sprite.x = amplitude * Math.sin((@timer * WAVE_SPEED) + (i * WAVE_SPACING)) end # Move bubbles sprite up and oscillate side to side @bubbles_sprite.x = (Graphics.width - @bubble_bitmap.width) / 2 @bubbles_sprite.x += MAX_BUBBLE_AMPLITUDE * Math.sin(@timer * BUBBLES_WAVE_SPEED) @bubbles_sprite.y = Graphics.height * (1 - (@timer * 1.2)) # Move splash sprite up if @timer >= @splash_rising_start proportion = (@timer - @splash_rising_start) / (@duration - @splash_rising_start) @splash_sprite.y = Graphics.height * (1 - (proportion * 2)) end # Move black sprite up if @timer >= @black_rising_start proportion = (@timer - @black_rising_start) / (@duration - @black_rising_start) @black_sprite.y = Graphics.height * (1 - proportion) end end end #============================================================================= # HGSS trainer outdoor day #============================================================================= class TwoBallPass < Transition_Base DURATION = 1.0 def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_half") @ball_bitmap = RPG::Cache.transition("ball_small") dispose if !@black_bitmap || !@ball_bitmap end def initialize_sprites @overworld_sprite.x = Graphics.width / 2 @overworld_sprite.y = Graphics.height / 2 @overworld_sprite.ox = @overworld_bitmap.width / 2 @overworld_sprite.oy = @overworld_bitmap.height / 2 # Balls that roll across the screen @ball_sprites = [] 2.times do |i| x = ((1 - i) * Graphics.width) + ((1 - (i * 2)) * @ball_bitmap.width / 2) y = (Graphics.height + (((i * 2) - 1) * @ball_bitmap.width)) / 2 @ball_sprites[i] = new_sprite(x, y, @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprites[i].z = 2 end # Black foreground sprites 2.times do |i| @sprites[i] = new_sprite((1 - (i * 2)) * Graphics.width, i * Graphics.height / 2, @black_bitmap) @sprites[i].z = 1 end @sprites[2] = new_sprite(0, Graphics.height / 2, @black_bitmap, 0, @black_bitmap.height / 2) @sprites[2].z = 1 @sprites[2].zoom_y = 0.0 end def set_up_timings @ball_start_x = [@ball_sprites[0].x, @ball_sprites[1].x] @ball_roll_end = @duration * 0.4 end def dispose_all # Dispose sprites if @ball_sprites @ball_sprites.each { |s| s&.dispose } @ball_sprites.clear end # Dispose bitmaps @black_bitmap&.dispose @ball_bitmap&.dispose end def update_anim if @timer <= @ball_roll_end # Roll ball sprites across screen proportion = @timer / @ball_roll_end total_distance = Graphics.width + @ball_bitmap.width @ball_sprites.each_with_index do |sprite, i| sprite.x = @ball_start_x[i] + (((2 * i) - 1) * (total_distance * proportion)) sprite.angle = ((2 * i) - 1) * 360 * proportion * 2 end else proportion = (@timer - @ball_roll_end) / (@duration - @ball_roll_end) # Hide ball sprites if @ball_sprites[0].visible @ball_sprites.each { |s| s.visible = false } end # Zoom in overworld sprite @overworld_sprite.zoom_x = 1.0 + (proportion * proportion) # Ends at 2x zoom @overworld_sprite.zoom_y = @overworld_sprite.zoom_x # Slide first two black bars across @sprites[0].x = Graphics.width * (1 - (proportion * proportion)) @sprites[1].x = Graphics.width * ((proportion * proportion) - 1) # Expand third black bar @sprites[2].zoom_y = 2.0 * proportion * proportion # Ends at 2x zoom end end end #============================================================================= # HGSS trainer outdoor night #============================================================================= class SpinBallSplit < Transition_Base DURATION = 1.0 def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_half") @ball_bitmap = RPG::Cache.transition("ball_large") dispose if !@black_bitmap || !@ball_bitmap end def initialize_sprites @overworld_sprite.visible = false @overworld_sprites = [] @black_sprites = [] @ball_sprites = [] 2.times do |i| # Overworld sprites (they split apart) @overworld_sprites[i] = new_sprite(Graphics.width / 2, Graphics.height / 2, @overworld_bitmap, Graphics.width / 2, (1 - i) * Graphics.height / 2) @overworld_sprites[i].src_rect.set(0, i * Graphics.height / 2, Graphics.width, Graphics.height / 2) # Black sprites @black_sprites[i] = new_sprite((1 - i) * Graphics.width, i * Graphics.height / 2, @black_bitmap, i * @black_bitmap.width, 0) @black_sprites[i].z = 1 # Ball sprites @ball_sprites[i] = new_sprite(Graphics.width / 2, Graphics.height / 2, @ball_bitmap, @ball_bitmap.width / 2, (1 - i) * @ball_bitmap.height / 2) @ball_sprites[i].z = 2 @ball_sprites[i].zoom_x = 0.0 @ball_sprites[i].zoom_y = 0.0 end end def set_up_timings @ball_spin_end = @duration * 0.4 @slide_start = @duration * 0.5 end def dispose_all # Dispose sprites if @overworld_sprites @overworld_sprites.each { |s| s&.dispose } @overworld_sprites.clear end if @black_sprites @black_sprites.each { |s| s&.dispose } @black_sprites.clear end if @ball_sprites @ball_sprites.each { |s| s&.dispose } @ball_sprites.clear end # Dispose bitmaps @black_bitmap&.dispose @ball_bitmap&.dispose end def update_anim if @timer < @ball_spin_end # Ball spin proportion = @timer / @ball_spin_end @ball_sprites[0].zoom_x = proportion @ball_sprites[0].zoom_y = proportion @ball_sprites[0].angle = 360 * (1 - proportion) elsif @timer < @slide_start # Fix zoom/angle of ball sprites if @ball_sprites[0].src_rect.height == @ball_bitmap.height @ball_sprites.each_with_index do |sprite, i| sprite.zoom_x = 1.0 sprite.zoom_y = 1.0 sprite.angle = 0 sprite.src_rect.set(0, i * @ball_bitmap.height / 2, @ball_bitmap.width, @ball_bitmap.height / 2) end end else # Split overworld/ball apart, move blackness in following them proportion = (@timer - @slide_start) / (@duration - @slide_start) @overworld_sprites.each_with_index do |sprite, i| sprite.x = (0.5 + (((i * 2) - 1) * proportion * proportion)) * Graphics.width sprite.zoom_x = 1.0 + (proportion * proportion) # Ends at 2x zoom sprite.zoom_y = sprite.zoom_x @black_sprites[i].x = sprite.x + ((1 - (i * 2)) * Graphics.width / 2) @ball_sprites[i].x = sprite.x end end end end #============================================================================= # HGSS trainer indoor day #============================================================================= class ThreeBallDown < Transition_Base DURATION = 2.0 NUM_SPRITES_X = 8 NUM_SPRITES_Y = 6 TOTAL_SPRITES = NUM_SPRITES_X * NUM_SPRITES_Y BALL_START_Y_OFFSETS = [400, 0, 100] def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_square") @ball_bitmap = RPG::Cache.transition("ball_small") if !@black_bitmap || !@ball_bitmap dispose return end @zoom_x_target = Graphics.width.to_f / (@black_bitmap.width * NUM_SPRITES_X) @zoom_y_target = Graphics.height.to_f / (@black_bitmap.height * NUM_SPRITES_Y) end def initialize_sprites @overworld_sprite.x = Graphics.width / 2 @overworld_sprite.y = Graphics.height / 2 @overworld_sprite.ox = @overworld_bitmap.width / 2 @overworld_sprite.oy = @overworld_bitmap.height / 2 # Black squares NUM_SPRITES_Y.times do |j| NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @sprites[idx_sprite] = new_sprite(i * @black_bitmap.width * @zoom_x_target, j * @black_bitmap.height * @zoom_y_target, @black_bitmap) @sprites[idx_sprite].visible = false end end # Falling balls @ball_sprites = [] 3.times do |i| @ball_sprites[i] = new_sprite((Graphics.width / 2) + ((i - 1) * 160), -@ball_bitmap.height - BALL_START_Y_OFFSETS[i], @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprites[i].z = 2 end end def set_up_timings @black_appear_start = @duration * 0.2 appear_order = [0, 4, 1, 6, 7, 2, 5, 3] period = @duration - @black_appear_start NUM_SPRITES_Y.times do |j| row_offset = NUM_SPRITES_Y - j - 1 NUM_SPRITES_X.times do |i| idx_sprite = (j * NUM_SPRITES_X) + i @timings[idx_sprite] = period * ((row_offset * NUM_SPRITES_X) + appear_order[i]) / TOTAL_SPRITES @timings[idx_sprite] += @black_appear_start end end end def dispose_all # Dispose sprites if @ball_sprites @ball_sprites.each { |s| s&.dispose } @ball_sprites.clear end # Dispose bitmaps @black_bitmap&.dispose @ball_bitmap&.dispose end def update_anim if @timer < @black_appear_start # Balls drop down screen while spinning proportion = @timer / @black_appear_start @ball_sprites.each_with_index do |sprite, i| sprite.y = -@ball_bitmap.height - BALL_START_Y_OFFSETS[i] sprite.y += (Graphics.height + BALL_START_Y_OFFSETS.max + (@ball_bitmap.height * 2)) * proportion sprite.angle = 1.5 * 360 * proportion * ([1, -1][(i == 2) ? 0 : 1]) end else if @ball_sprites[0].visible @ball_sprites.each { |s| s.visible = false } end # Black squares appear @timings.each_with_index do |timing, i| next if timing < 0 || @timer < timing @sprites[i].visible = true @timings[i] = -1 end # Zoom in overworld sprite proportion = (@timer - @black_appear_start) / (@duration - @black_appear_start) @overworld_sprite.zoom_x = 1.0 + (proportion * proportion) # Ends at 2x zoom @overworld_sprite.zoom_y = @overworld_sprite.zoom_x end end end #============================================================================= # HGSS trainer indoor night # HGSS trainer cave #============================================================================= class BallDown < Transition_Base DURATION = 0.9 def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_half") @curve_bitmap = RPG::Cache.transition("black_curve") @ball_bitmap = RPG::Cache.transition("ball_small") dispose if !@black_bitmap || !@curve_bitmap || !@ball_bitmap end def initialize_sprites @overworld_sprite.x = Graphics.width / 2 @overworld_sprite.y = Graphics.height / 2 @overworld_sprite.ox = @overworld_bitmap.width / 2 @overworld_sprite.oy = @overworld_bitmap.height / 2 # Black sprites @sprites[0] = new_sprite(0, -@curve_bitmap.height, @black_bitmap, 0, @black_bitmap.height) @sprites[0].z = 1 @sprites[0].zoom_y = 2.0 @sprites[1] = new_sprite(0, -@curve_bitmap.height, @curve_bitmap) @sprites[1].z = 1 # Ball sprite @ball_sprite = new_sprite(Graphics.width / 2, -@ball_bitmap.height / 2, @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprite.z = 2 @ball_sprite.zoom_x = 0.0 @ball_sprite.zoom_y = 0.0 end def set_up_timings @ball_appear_end = @duration * 0.7 end def dispose_all # Dispose sprites @ball_sprite&.dispose # Dispose bitmaps @black_bitmap&.dispose @curve_bitmap&.dispose @ball_bitmap&.dispose end def update_anim if @timer <= @ball_appear_end # Make ball drop down and zoom in proportion = @timer / @ball_appear_end @ball_sprite.y = (-@ball_bitmap.height / 2) + ((Graphics.height + (@ball_bitmap.height * 3)) * proportion * proportion) @ball_sprite.angle = -1.5 * 360 * proportion @ball_sprite.zoom_x = 3 * proportion * proportion @ball_sprite.zoom_y = @ball_sprite.zoom_x else @ball_sprite.visible = false # Black curve and blackness descends proportion = (@timer - @ball_appear_end) / (@duration - @ball_appear_end) @sprites.each do |sprite| sprite.y = -@curve_bitmap.height + ((Graphics.height + @curve_bitmap.height) * proportion) end # Zoom in overworld sprite @overworld_sprite.zoom_x = 1.0 + (proportion * proportion) # Ends at 2x zoom @overworld_sprite.zoom_y = @overworld_sprite.zoom_x end end end #============================================================================= # HGSS trainer water day #============================================================================= class WavyThreeBallUp < Transition_Base DURATION = 1.1 BALL_OFFSETS = [1.5, 3.25, 2.5] MAX_WAVE_AMPLITUDE = 24 WAVE_SPACING = Math::PI / 24 # Density of overworld waves (48 strips per wave) WAVE_SPEED = Math::PI * 4 # Speed of overworld waves going up the screen def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_half") @ball_bitmap = RPG::Cache.transition("ball_small") dispose if !@black_bitmap || !@ball_bitmap end def initialize_sprites @overworld_sprite.visible = false # Overworld strips (they go all wavy) rect = Rect.new(0, 0, Graphics.width, 4) (Graphics.height / 4).times do |i| @sprites[i] = new_sprite(0, i * 4, @overworld_bitmap) @sprites[i].z = 2 rect.y = i * 4 @sprites[i].src_rect = rect end # Ball sprites @ball_sprites = [] 3.times do |i| @ball_sprites[i] = new_sprite(((2 * i) + 1) * Graphics.width / 6, BALL_OFFSETS[i] * Graphics.height, @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprites[i].z = 4 end # Black columns that follow the ball sprites @black_trail_sprites = [] 3.times do |i| @black_trail_sprites[i] = new_sprite((i - 1) * Graphics.width * 2 / 3, BALL_OFFSETS[i] * Graphics.height, @black_bitmap) @black_trail_sprites[i].z = 3 @black_trail_sprites[i].zoom_y = 2.0 end end def set_up_timings @ball_rising_start = @duration * 0.4 end def dispose_all # Dispose sprites if @ball_sprites @ball_sprites.each { |s| s&.dispose } @ball_sprites.clear end if @black_trail_sprites @black_trail_sprites.each { |s| s&.dispose } @black_trail_sprites.clear end # Dispose bitmaps @black_bitmap&.dispose @ball_bitmap&.dispose end def update_anim # Make overworld wave strips oscillate amplitude = MAX_WAVE_AMPLITUDE * [@timer / 0.1, 1].min # Build up to max in 0.1 seconds @sprites.each_with_index do |sprite, i| sprite.x = (1 - ((i % 2) * 2)) * amplitude * Math.sin((@timer * WAVE_SPEED) + (i * WAVE_SPACING)) end # Move balls and trailing blackness up if @timer >= @ball_rising_start proportion = (@timer - @ball_rising_start) / (@duration - @ball_rising_start) @ball_sprites.each_with_index do |sprite, i| sprite.y = (BALL_OFFSETS[i] * Graphics.height) - (Graphics.height * 3.5 * proportion) sprite.angle = [-1, -1, 1][i] * 360 * 2 * proportion @black_trail_sprites[i].y = sprite.y @black_trail_sprites[i].y = 0 if @black_trail_sprites[i].y < 0 end end end end #============================================================================= # HGSS trainer water night #============================================================================= class WavySpinBall < Transition_Base DURATION = 1.0 MAX_WAVE_AMPLITUDE = 24 WAVE_SPACING = Math::PI / 24 # Density of overworld waves (48 strips per wave) WAVE_SPEED = Math::PI * 4 # Speed of overworld waves going up the screen def initialize_bitmaps @black_bitmap = RPG::Cache.transition("black_half") @ball_bitmap = RPG::Cache.transition("ball_large") dispose if !@black_bitmap || !@ball_bitmap end def initialize_sprites @overworld_sprite.visible = false # Overworld strips (they go all wavy) rect = Rect.new(0, 0, Graphics.width, 4) (Graphics.height / 4).times do |i| @sprites[i] = new_sprite(0, i * 4, @overworld_bitmap) @sprites[i].z = 2 rect.y = i * 4 @sprites[i].src_rect = rect end # Ball sprite @ball_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprite.z = 3 @ball_sprite.opacity = 0 # Black sprite @black_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @black_bitmap, @black_bitmap.width / 2, @black_bitmap.height / 2) @black_sprite.z = 4 @black_sprite.zoom_x = 0.0 @black_sprite.zoom_y = 0.0 end def set_up_timings @ball_appear_end = @duration * 0.4 @black_appear_start = @duration * 0.5 end def dispose_all # Dispose sprites @ball_sprite&.dispose @black_sprite&.dispose # Dispose bitmaps @black_bitmap&.dispose @ball_bitmap&.dispose end def update_anim # Make overworld wave strips oscillate amplitude = MAX_WAVE_AMPLITUDE * [@timer / 0.1, 1].min # Build up to max in 0.1 seconds @sprites.each_with_index do |sprite, i| sprite.x = (1 - ((i % 2) * 2)) * amplitude * Math.sin((@timer * WAVE_SPEED) + (i * WAVE_SPACING)) end if @timer <= @ball_appear_end # Fade in ball while spinning proportion = @timer / @ball_appear_end @ball_sprite.opacity = 255 * proportion @ball_sprite.angle = -360 * proportion elsif @timer <= @black_appear_start # Fix opacity/angle of ball sprite @ball_sprite.opacity = 255 @ball_sprite.angle = 0 else # Spread blackness from centre proportion = (@timer - @black_appear_start) / (@duration - @black_appear_start) @black_sprite.zoom_x = proportion @black_sprite.zoom_y = proportion * 2 end end end #============================================================================= # HGSS double trainers #============================================================================= class FourBallBurst < Transition_Base DURATION = 0.9 def initialize_bitmaps @black_1_bitmap = RPG::Cache.transition("black_wedge_1") @black_2_bitmap = RPG::Cache.transition("black_wedge_2") @black_3_bitmap = RPG::Cache.transition("black_wedge_3") @black_4_bitmap = RPG::Cache.transition("black_wedge_4") @ball_bitmap = RPG::Cache.transition("ball_small") dispose if !@black_1_bitmap || !@black_2_bitmap || !@black_3_bitmap || !@black_4_bitmap || !@ball_bitmap end def initialize_sprites # Ball sprites @ball_sprites = [] 4.times do |i| @ball_sprites[i] = new_sprite(Graphics.width / 2, Graphics.height / 2, @ball_bitmap, @ball_bitmap.width / 2, @ball_bitmap.height / 2) @ball_sprites[i].z = [2, 1, 3, 0][i] end # Black wedges 4.times do |i| b = [@black_1_bitmap, @black_2_bitmap, @black_3_bitmap, @black_4_bitmap][i] @sprites[i] = new_sprite((i == 1) ? 0 : Graphics.width / 2, (i == 2) ? 0 : Graphics.height / 2, b, (i.even?) ? b.width / 2 : 0, (i.even?) ? 0 : b.height / 2) @sprites[i].zoom_x = 0.0 if i.even? @sprites[i].zoom_y = 0.0 if i.odd? @sprites[i].visible = false end end def set_up_timings @ball_appear_end = @duration * 0.4 end def dispose_all # Dispose sprites @ball_sprites.each { |s| s&.dispose } @ball_sprites.clear # Dispose bitmaps @black_1_bitmap&.dispose @black_2_bitmap&.dispose @black_3_bitmap&.dispose @black_4_bitmap&.dispose @ball_bitmap&.dispose end def update_anim if @timer <= @ball_appear_end # Balls fly out from centre of screen proportion = @timer / @ball_appear_end ball_travel_x = (Graphics.width + (@ball_bitmap.width * 2)) / 2 ball_travel_y = (Graphics.height + (@ball_bitmap.height * 2)) / 2 @ball_sprites.each_with_index do |sprite, i| sprite.x = (Graphics.width / 2) + ([0, 1, 0, -1][i] * ball_travel_x * proportion) if i.odd? sprite.y = (Graphics.height / 2) + ([1, 0, -1, 0][i] * ball_travel_y * proportion) if i.even? end else # Black wedges expand to fill screen proportion = (@timer - @ball_appear_end) / (@duration - @ball_appear_end) @sprites.each_with_index do |sprite, i| sprite.visible = true sprite.zoom_x = proportion if i.even? sprite.zoom_y = proportion if i.odd? end end end end #============================================================================= # HGSS VS Trainer animation # Uses $game_temp.transition_animation_data, and expects it to be an array # like so: [:TRAINERTYPE, "display name"] # Bar graphics are named hgss_vsBar_TRAINERTYPE.png. # Trainer sprites are named hgss_vs_TRAINERTYPE.png. #============================================================================= class VSTrainer < Transition_Base DURATION = 4.0 BAR_Y = 80 BAR_SCROLL_SPEED = 1800 BAR_MASK = [8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7] FOE_SPRITE_X_LIMIT = 384 # Slides to here before jumping to final position FOE_SPRITE_X = 428 # Final position of foe sprite def initialize_bitmaps @bar_bitmap = RPG::Cache.transition("hgss_vsBar_#{$game_temp.transition_animation_data[0]}") @vs_1_bitmap = RPG::Cache.transition("hgss_vs1") @vs_2_bitmap = RPG::Cache.transition("hgss_vs2") @foe_bitmap = RPG::Cache.transition("hgss_vs_#{$game_temp.transition_animation_data[0]}") @black_bitmap = RPG::Cache.transition("black_half") dispose if !@bar_bitmap || !@vs_1_bitmap || !@vs_2_bitmap || !@foe_bitmap || !@black_bitmap end def initialize_sprites @flash_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @flash_viewport.z = 99999 @flash_viewport.color = Color.new(255, 255, 255, 0) # Background black @rear_black_sprite = new_sprite(0, 0, @black_bitmap) @rear_black_sprite.z = 1 @rear_black_sprite.zoom_y = 2.0 @rear_black_sprite.opacity = 224 @rear_black_sprite.visible = false # Bar sprites (need 2 of them to make them loop around) ((Graphics.width.to_f / @bar_bitmap.width).ceil + 1).times do |i| spr = new_sprite(@bar_bitmap.width * i, BAR_Y, @bar_bitmap) spr.z = 2 @sprites.push(spr) end # Overworld sprite @bar_mask_sprite = new_sprite(0, 0, @overworld_bitmap.clone) @bar_mask_sprite.z = 3 # VS logo @vs_x = 144 @vs_y = @sprites[0].y + (@sprites[0].height / 2) @vs_main_sprite = new_sprite(@vs_x, @vs_y, @vs_1_bitmap, @vs_1_bitmap.width / 2, @vs_1_bitmap.height / 2) @vs_main_sprite.z = 4 @vs_main_sprite.visible = false @vs_1_sprite = new_sprite(@vs_x, @vs_y, @vs_2_bitmap, @vs_2_bitmap.width / 2, @vs_2_bitmap.height / 2) @vs_1_sprite.z = 5 @vs_1_sprite.zoom_x = 2.0 @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x @vs_1_sprite.visible = false @vs_2_sprite = new_sprite(@vs_x, @vs_y, @vs_2_bitmap, @vs_2_bitmap.width / 2, @vs_2_bitmap.height / 2) @vs_2_sprite.z = 6 @vs_2_sprite.zoom_x = 2.0 @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x @vs_2_sprite.visible = false # Foe sprite @foe_sprite = new_sprite(Graphics.width + @foe_bitmap.width, @sprites[0].y + @sprites[0].height - 12, @foe_bitmap, @foe_bitmap.width / 2, @foe_bitmap.height) @foe_sprite.z = 7 @foe_sprite.color = Color.black # Sprite with foe's name written in it @text_sprite = BitmapSprite.new(Graphics.width, @bar_bitmap.height, @viewport) @text_sprite.y = BAR_Y @text_sprite.z = 8 @text_sprite.visible = false pbSetSystemFont(@text_sprite.bitmap) pbDrawTextPositions(@text_sprite.bitmap, [[$game_temp.transition_animation_data[1], 244, 86, 0, Color.new(248, 248, 248), Color.new(72, 80, 80)]]) # Foreground black @black_sprite = new_sprite(0, 0, @black_bitmap) @black_sprite.z = 10 @black_sprite.zoom_y = 2.0 @black_sprite.visible = false end def set_up_timings @bar_x = 0 @bar_appear_end = 0.2 # Starts appearing at 0.0 @vs_appear_start = 0.7 @vs_appear_start_2 = 0.9 @vs_shrink_time = @vs_appear_start_2 - @vs_appear_start @vs_appear_final = @vs_appear_start_2 + @vs_shrink_time @foe_appear_start = 1.25 @foe_appear_end = 1.4 @flash_start = 1.9 @flash_duration = 0.25 @fade_to_white_start = 3.0 @fade_to_white_end = 3.5 @fade_to_black_start = 3.8 end def dispose_all # Dispose sprites @rear_black_sprite&.dispose @bar_mask_sprite&.dispose @vs_main_sprite&.dispose @vs_1_sprite&.dispose @vs_2_sprite&.dispose @foe_sprite&.dispose @text_sprite&.dispose @black_sprite&.dispose # Dispose bitmaps @bar_bitmap&.dispose @vs_1_bitmap&.dispose @vs_2_bitmap&.dispose @foe_bitmap&.dispose @black_bitmap&.dispose # Dispose viewport @flash_viewport&.dispose end def update_anim # Bar scrolling @bar_x -= Graphics.delta_s * BAR_SCROLL_SPEED @bar_x += @bar_bitmap.width if @bar_x <= -@bar_bitmap.width @sprites.each_with_index { |spr, i| spr.x = @bar_x + (i * @bar_bitmap.width) } # Vibrate VS sprite vs_phase = (@timer * 30).to_i % 3 @vs_main_sprite.x = @vs_x + [0, 4, 0][vs_phase] @vs_main_sprite.y = @vs_y + [0, 0, -4][vs_phase] if @timer >= @fade_to_black_start # Fade to black @black_sprite.visible = true proportion = (@timer - @fade_to_black_start) / (@duration - @fade_to_black_start) @flash_viewport.color.alpha = 255 * (1 - proportion) elsif @timer >= @fade_to_white_start # Slowly fade to white proportion = (@timer - @fade_to_white_start) / (@fade_to_white_end - @fade_to_white_start) @flash_viewport.color.alpha = 255 * proportion elsif @timer >= @flash_start + @flash_duration @flash_viewport.color.alpha = 0 elsif @timer >= @flash_start # Flash the screen white proportion = (@timer - @flash_start) / @flash_duration if proportion >= 0.5 @flash_viewport.color.alpha = 320 * 2 * (1 - proportion) @rear_black_sprite.visible = true @foe_sprite.color.alpha = 0 @text_sprite.visible = true else @flash_viewport.color.alpha = 320 * 2 * proportion end elsif @timer >= @foe_appear_end @foe_sprite.x = FOE_SPRITE_X elsif @timer >= @foe_appear_start # Foe sprite appears proportion = (@timer - @foe_appear_start) / (@foe_appear_end - @foe_appear_start) start_x = Graphics.width + (@foe_bitmap.width / 2) @foe_sprite.x = start_x + ((FOE_SPRITE_X_LIMIT - start_x) * proportion) elsif @timer >= @vs_appear_final @vs_1_sprite.visible = false elsif @timer >= @vs_appear_start_2 # Temp VS sprites enlarge and shrink again if @vs_2_sprite.visible @vs_2_sprite.zoom_x = 1.6 - (0.8 * (@timer - @vs_appear_start_2) / @vs_shrink_time) @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x if @vs_2_sprite.zoom_x <= 1.2 @vs_2_sprite.visible = false @vs_main_sprite.visible = true end end @vs_1_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start_2) / @vs_shrink_time) @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x elsif @timer >= @vs_appear_start # Temp VS sprites appear and start shrinking @vs_2_sprite.visible = true @vs_2_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start) / @vs_shrink_time) @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x if @vs_1_sprite.visible || @vs_2_sprite.zoom_x <= 1.6 # Halfway between 2.0 and 1.2 @vs_1_sprite.visible = true @vs_1_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start - (@vs_shrink_time / 2)) / @vs_shrink_time) @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x end elsif @timer >= @bar_appear_end @bar_mask_sprite.visible = false else start_x = Graphics.width * (1 - (@timer / @bar_appear_end)) color = Color.new(0, 0, 0, 0) # Transparent (@sprites[0].height / 2).times do |i| x = start_x - (BAR_MASK[i % BAR_MASK.length] * 4) @bar_mask_sprite.bitmap.fill_rect(x, BAR_Y + (i * 2), @bar_mask_sprite.width - x, 2, color) end end end end #============================================================================= # HGSS VS Elite Four/Champion animation # Uses $game_temp.transition_animation_data, and expects it to be an array # like so: [:TRAINERTYPE, "display name", "player sprite name minus 'vsE4_'"] # Bar graphics are named vsE4Bar_TRAINERTYPE.png. # Trainer sprites are named vsE4_TRAINERTYPE.png. #============================================================================= class VSEliteFour < Transition_Base DURATION = 3.5 BAR_X_INDENT = 48 BAR_Y_INDENT = 64 # = height of trainer sprite / 2 BAR_OVERSHOOT = 20 TRAINER_X_OFFSET = 160 TRAINER_Y_OFFSET = 8 BAR_HEIGHT = 192 # = Graphics.height / 2 FOE_SPRITE_X_LIMIT = 384 # Slides to here before jumping to final position FOE_SPRITE_X = 428 # Final position of foe sprite def initialize_bitmaps @bar_bitmap = RPG::Cache.transition("vsE4Bar_#{$game_temp.transition_animation_data[0]}") @vs_1_bitmap = RPG::Cache.transition("hgss_vs1") @vs_2_bitmap = RPG::Cache.transition("hgss_vs2") @player_bitmap = RPG::Cache.transition("vsE4_#{$game_temp.transition_animation_data[2]}") @foe_bitmap = RPG::Cache.transition("vsE4_#{$game_temp.transition_animation_data[0]}") @black_bitmap = RPG::Cache.transition("black_half") dispose if !@bar_bitmap || !@vs_1_bitmap || !@vs_2_bitmap || !@foe_bitmap || !@black_bitmap @num_bar_frames = @bar_bitmap.height / BAR_HEIGHT end def initialize_sprites @flash_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @flash_viewport.z = 99999 @flash_viewport.color = Color.new(255, 255, 255, 0) # Background black @rear_black_sprite = new_sprite(0, 0, @black_bitmap) @rear_black_sprite.z = 1 @rear_black_sprite.zoom_y = 2.0 @rear_black_sprite.opacity = 192 @rear_black_sprite.visible = false # Player's bar sprite @player_bar_x = -BAR_X_INDENT @player_bar_start_x = @player_bar_x - (@bar_bitmap.width / 2) @player_bar_y = BAR_Y_INDENT @player_bar_sprite = new_sprite(@player_bar_start_x, @player_bar_y, @bar_bitmap) @player_bar_sprite.z = 2 @player_bar_sprite.src_rect.width = @bar_bitmap.width / 2 @player_bar_sprite.src_rect.height = BAR_HEIGHT # Foe's bar sprite @foe_bar_x = Graphics.width + BAR_X_INDENT - (@bar_bitmap.width / 2) @foe_bar_start_x = @foe_bar_x + (@bar_bitmap.width / 2) @foe_bar_y = Graphics.height - BAR_HEIGHT - BAR_Y_INDENT @foe_bar_sprite = new_sprite(@foe_bar_start_x, @foe_bar_y, @bar_bitmap) @foe_bar_sprite.z = 2 @foe_bar_sprite.src_rect.x = @bar_bitmap.width / 2 @foe_bar_sprite.src_rect.width = @bar_bitmap.width / 2 @foe_bar_sprite.src_rect.height = BAR_HEIGHT # Player sprite @player_sprite = new_sprite(@player_bar_sprite.x + TRAINER_X_OFFSET, @player_bar_sprite.y + BAR_HEIGHT - TRAINER_Y_OFFSET, @player_bitmap, @player_bitmap.width / 2, @player_bitmap.height) @player_sprite.z = 7 @player_sprite.color = Color.black # Foe sprite @foe_sprite = new_sprite(@foe_bar_sprite.x + (@bar_bitmap.width / 2) - TRAINER_X_OFFSET, @foe_bar_sprite.y + @foe_bitmap.height - TRAINER_Y_OFFSET, @foe_bitmap, @foe_bitmap.width / 2, @foe_bitmap.height) @foe_sprite.z = 7 @foe_sprite.color = Color.black # Sprite with foe's name written in it @text_sprite = BitmapSprite.new(@bar_bitmap.width / 2, BAR_HEIGHT, @viewport) @text_sprite.x = @foe_bar_start_x @text_sprite.y = @foe_bar_y @text_sprite.z = 8 pbSetSystemFont(@text_sprite.bitmap) pbDrawTextPositions(@text_sprite.bitmap, [[$game_temp.transition_animation_data[1], 160, 86, 0, Color.new(248, 248, 248), Color.new(72, 80, 80)]]) # VS logo @vs_main_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @vs_1_bitmap, @vs_1_bitmap.width / 2, @vs_1_bitmap.height / 2) @vs_main_sprite.z = 14 @vs_main_sprite.visible = false @vs_1_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @vs_2_bitmap, @vs_2_bitmap.width / 2, @vs_2_bitmap.height / 2) @vs_1_sprite.z = 15 @vs_1_sprite.zoom_x = 2.0 @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x @vs_1_sprite.visible = false @vs_2_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @vs_2_bitmap, @vs_2_bitmap.width / 2, @vs_2_bitmap.height / 2) @vs_2_sprite.z = 16 @vs_2_sprite.zoom_x = 2.0 @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x @vs_2_sprite.visible = false # Foreground black @black_sprite = new_sprite(0, 0, @black_bitmap) @black_sprite.z = 20 @black_sprite.zoom_y = 2.0 @black_sprite.visible = false end def set_up_timings @flash_1_start = 0.0 @flash_1_duration = 0.25 @bar_appear_start = 0.5 @bar_appear_end = 0.7 @vs_appear_start = 0.6 @vs_appear_start_2 = 0.8 @vs_shrink_time = @vs_appear_start_2 - @vs_appear_start @vs_appear_final = @vs_appear_start_2 + @vs_shrink_time @flash_start = 1.7 @flash_duration = 0.35 @fade_to_white_start = 2.7 @fade_to_white_end = 3.0 @fade_to_black_start = 3.3 end def dispose_all # Dispose sprites @rear_black_sprite&.dispose @player_bar_sprite&.dispose @foe_bar_sprite&.dispose @player_sprite&.dispose @foe_sprite&.dispose @text_sprite&.dispose @vs_main_sprite&.dispose @vs_1_sprite&.dispose @vs_2_sprite&.dispose @black_sprite&.dispose # Dispose bitmaps @bar_bitmap&.dispose @vs_1_bitmap&.dispose @vs_2_bitmap&.dispose @player_bitmap&.dispose @foe_bitmap&.dispose @black_bitmap&.dispose # Dispose viewport @flash_viewport&.dispose end def update_anim # Bars/trainer sprites slide in if @timer > @bar_appear_end @player_bar_sprite.x = @player_bar_x @player_sprite.x = @player_bar_sprite.x + TRAINER_X_OFFSET @foe_bar_sprite.x = @foe_bar_x @foe_sprite.x = @foe_bar_sprite.x + (@bar_bitmap.width / 2) - TRAINER_X_OFFSET @text_sprite.x = @foe_bar_sprite.x elsif @timer > @bar_appear_start # Bars/trainer sprites slide in proportion = (@timer - @bar_appear_start) / (@bar_appear_end - @bar_appear_start) sqrt_proportion = Math.sqrt(proportion) @player_bar_sprite.x = @player_bar_start_x + ((@player_bar_x + BAR_OVERSHOOT - @player_bar_start_x) * sqrt_proportion) @player_sprite.x = @player_bar_sprite.x + TRAINER_X_OFFSET @foe_bar_sprite.x = @foe_bar_start_x + ((@foe_bar_x - BAR_OVERSHOOT - @foe_bar_start_x) * sqrt_proportion) @foe_sprite.x = @foe_bar_sprite.x + (@bar_bitmap.width / 2) - TRAINER_X_OFFSET @text_sprite.x = @foe_bar_sprite.x end # Animate bars if @timer >= @flash_start + (0.33 * @flash_duration) bar_phase = (@timer * 30).to_i % @num_bar_frames @player_bar_sprite.src_rect.y = bar_phase * BAR_HEIGHT @foe_bar_sprite.src_rect.y = bar_phase * BAR_HEIGHT end # Vibrate VS sprite vs_phase = (@timer * 30).to_i % 3 @vs_main_sprite.x = (Graphics.width / 2) + [0, 4, 0][vs_phase] @vs_main_sprite.y = (Graphics.height / 2) + [0, 0, -4][vs_phase] # VS sprites appearing if @timer >= @vs_appear_final @vs_1_sprite.visible = false elsif @timer >= @vs_appear_start_2 # Temp VS sprites enlarge and shrink again if @vs_2_sprite.visible @vs_2_sprite.zoom_x = 1.6 - (0.8 * (@timer - @vs_appear_start_2) / @vs_shrink_time) @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x if @vs_2_sprite.zoom_x <= 1.2 @vs_2_sprite.visible = false @vs_main_sprite.visible = true end end @vs_1_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start_2) / @vs_shrink_time) @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x elsif @timer >= @vs_appear_start # Temp VS sprites appear and start shrinking @vs_2_sprite.visible = true @vs_2_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start) / @vs_shrink_time) @vs_2_sprite.zoom_y = @vs_2_sprite.zoom_x if @vs_1_sprite.visible || @vs_2_sprite.zoom_x <= 1.6 # Halfway between 2.0 and 1.2 @vs_1_sprite.visible = true @vs_1_sprite.zoom_x = 2.0 - (0.8 * (@timer - @vs_appear_start - (@vs_shrink_time / 2)) / @vs_shrink_time) @vs_1_sprite.zoom_y = @vs_1_sprite.zoom_x end end # Flash white (two flashes) if @timer >= @flash_start + @flash_duration @flash_viewport.color.alpha = 0 elsif @timer >= @flash_start # Flash the screen white (coming from white lasts twice as long as going to white) proportion = (@timer - @flash_start) / @flash_duration if proportion >= 0.33 # Coming from white @flash_viewport.color.alpha = 320 * 3 * (1 - proportion) / 2 @player_sprite.color.alpha = 0 @foe_sprite.color.alpha = 0 else # Going to white @flash_viewport.color.alpha = 320 * 3 * proportion end elsif @timer >= @flash_1_start + @flash_1_duration @flash_viewport.color.alpha = 0 elsif @timer >= @flash_1_start # Flash the screen white proportion = (@timer - @flash_1_start) / @flash_1_duration if proportion >= 0.5 # Coming from white @flash_viewport.color.alpha = 320 * 2 * (1 - proportion) @rear_black_sprite.visible = true else # Going to white @flash_viewport.color.alpha = 320 * 2 * proportion end end # Fade to white at end if @timer >= @fade_to_black_start # Fade to black @black_sprite.visible = true proportion = (@timer - @fade_to_black_start) / (@duration - @fade_to_black_start) @flash_viewport.color.alpha = 255 * (1 - proportion) elsif @timer >= @fade_to_white_start @text_sprite.visible = false # Slowly fade to white proportion = (@timer - @fade_to_white_start) / (@fade_to_white_end - @fade_to_white_start) @flash_viewport.color.alpha = 255 * proportion # Move bars and trainer sprites off-screen dist = BAR_Y_INDENT + BAR_HEIGHT @player_bar_sprite.x = @player_bar_x - (dist * proportion) @player_bar_sprite.y = @player_bar_y - (dist * proportion) @player_sprite.x = @player_bar_sprite.x + TRAINER_X_OFFSET @player_sprite.y = @player_bar_sprite.y + BAR_HEIGHT - TRAINER_Y_OFFSET @foe_bar_sprite.x = @foe_bar_x + (dist * proportion) @foe_bar_sprite.y = @foe_bar_y + (dist * proportion) @foe_sprite.x = @foe_bar_sprite.x + (@bar_bitmap.width / 2) - TRAINER_X_OFFSET @foe_sprite.y = @foe_bar_sprite.y + @foe_bitmap.height - TRAINER_Y_OFFSET end end end #============================================================================= # HGSS Rocket Grunt trainer(s) #============================================================================= class RocketGrunt < Transition_Base DURATION = 1.6 ROCKET_X = [ 1.5, -0.5, -0.5, 0.75, 1.5, -0.5] # * Graphics.width ROCKET_Y = [-0.5, 1.0, -0.5, 1.5, 0.5, 0.75] # * Graphics.height ROCKET_ANGLE = [ 1, 0.5, -1.5, -1, -1.5, 0.5] # * 360 * sprite.zoom_x def initialize_bitmaps @black_1_bitmap = RPG::Cache.transition("black_wedge_1") @black_2_bitmap = RPG::Cache.transition("black_wedge_2") @black_3_bitmap = RPG::Cache.transition("black_wedge_3") @black_4_bitmap = RPG::Cache.transition("black_wedge_4") @rocket_bitmap = RPG::Cache.transition("rocket_logo") dispose if !@black_1_bitmap || !@black_2_bitmap || !@black_3_bitmap || !@black_4_bitmap || !@rocket_bitmap end def initialize_sprites # Rocket sprites @rocket_sprites = [] ROCKET_X.length.times do |i| @rocket_sprites[i] = new_sprite( ROCKET_X[i] * Graphics.width, ROCKET_Y[i] * Graphics.height, @rocket_bitmap, @rocket_bitmap.width / 2, @rocket_bitmap.height / 2 ) end # Black wedges 4.times do |i| b = [@black_1_bitmap, @black_2_bitmap, @black_3_bitmap, @black_4_bitmap][i] @sprites[i] = new_sprite((i == 1) ? 0 : Graphics.width / 2, (i == 2) ? 0 : Graphics.height / 2, b, (i.even?) ? b.width / 2 : 0, (i.even?) ? 0 : b.height / 2) @sprites[i].zoom_x = 0.0 if i.even? @sprites[i].zoom_y = 0.0 if i.odd? @sprites[i].visible = false end end def set_up_timings @rocket_appear_end = @duration * 0.75 @rocket_appear_delay = 1.0 / (ROCKET_X.length + 1) @rocket_appear_time = @rocket_appear_delay * 2 # 2 logos on screen at once end def dispose_all # Dispose sprites @rocket_sprites.each { |s| s&.dispose } @rocket_sprites.clear # Dispose bitmaps @black_1_bitmap&.dispose @black_2_bitmap&.dispose @black_3_bitmap&.dispose @black_4_bitmap&.dispose @rocket_bitmap&.dispose end def update_anim if @timer <= @rocket_appear_end # Rocket logos fly in from edges of screen proportion = @timer / @rocket_appear_end @rocket_sprites.each_with_index do |sprite, i| next if !sprite.visible start_time = i * @rocket_appear_delay next if proportion < start_time single_proportion = (proportion - start_time) / @rocket_appear_time sqrt_single_proportion = Math.sqrt(single_proportion) sprite.x = (ROCKET_X[i] + ((0.5 - ROCKET_X[i]) * sqrt_single_proportion)) * Graphics.width sprite.y = (ROCKET_Y[i] + ((0.5 - ROCKET_Y[i]) * sqrt_single_proportion)) * Graphics.height sprite.zoom_x = 2.5 * (1 - single_proportion) sprite.zoom_y = sprite.zoom_x sprite.angle = sprite.zoom_x * ROCKET_ANGLE[i] * 360 sprite.visible = false if sprite.zoom_x <= 0 end else @rocket_sprites.last.visible = false # Black wedges expand to fill screen proportion = (@timer - @rocket_appear_end) / (@duration - @rocket_appear_end) @sprites.each_with_index do |sprite, i| sprite.visible = true sprite.zoom_x = proportion if i.even? sprite.zoom_y = proportion if i.odd? end end end end #============================================================================= # HGSS VS Team Rocket Admin animation # Uses $game_temp.transition_animation_data, and expects it to be an array # like so: [:TRAINERTYPE, "display name"] # Bar graphics are named hgss_vsBar_TRAINERTYPE.png. # Trainer sprites are named hgss_vs_TRAINERTYPE.png. #============================================================================= class VSRocketAdmin < Transition_Base DURATION = 3.1 STROBE_SCROLL_SPEED = 1440 FOE_SPRITE_Y = 318 def initialize_bitmaps @strobes_bitmap = RPG::Cache.transition("rocket_strobes") @bg_1_bitmap = RPG::Cache.transition("rocket_bg_1") @bg_2_bitmap = RPG::Cache.transition("rocket_bg_2") @foe_bitmap = RPG::Cache.transition("rocket_#{$game_temp.transition_animation_data[0]}") @black_bitmap = RPG::Cache.transition("black_half") dispose if !@strobes_bitmap || !@bg_1_bitmap || !@bg_2_bitmap || !@foe_bitmap || !@black_bitmap end def initialize_sprites @flash_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @flash_viewport.z = 99999 @flash_viewport.color = Color.new(255, 255, 255, 0) # Strobe sprites (need 2 of them to make them loop around) ((Graphics.width.to_f / @strobes_bitmap.width).ceil + 1).times do |i| spr = new_sprite(@strobes_bitmap.width * i, 0, @strobes_bitmap) spr.z = 1 spr.opacity = 0 @sprites.push(spr) end # First bg sprite @bg_1_sprite = new_sprite(0, Graphics.height / 2, @bg_1_bitmap) @bg_1_sprite.z = 3 @bg_1_sprite.src_rect.height = 0 # Second bg sprite @bg_2_sprite = new_sprite(0, 0, @bg_2_bitmap) @bg_2_sprite.z = 5 @bg_2_sprite.opacity = 0 # Foe sprite @foe_sprite = new_sprite(Graphics.width + @foe_bitmap.width, FOE_SPRITE_Y, @foe_bitmap, @foe_bitmap.width / 2, @foe_bitmap.height) @foe_sprite.z = 7 # Sprite with foe's name written in it @text_sprite = BitmapSprite.new(Graphics.width, Graphics.height - FOE_SPRITE_Y, @viewport) @text_sprite.y = FOE_SPRITE_Y @text_sprite.z = 8 @text_sprite.visible = false pbSetSystemFont(@text_sprite.bitmap) pbDrawTextPositions(@text_sprite.bitmap, [[$game_temp.transition_animation_data[1], 272, 8, 0, Color.new(248, 248, 248), Color.new(72, 80, 80)]]) # Foreground black @black_sprite = new_sprite(0, 0, @black_bitmap) @black_sprite.z = 10 @black_sprite.zoom_y = 2.0 @black_sprite.visible = false end def set_up_timings @strobes_x = 0 @strobe_appear_end = 0.15 # Starts appearing at 0.0 # White flash between these two times @bg_1_appear_start = 0.5 @bg_1_appear_end = 0.65 @bg_2_appear_start = 1.0 # Also when foe sprite/name start appearing @bg_2_appear_end = 1.1 # Also when foe sprite/name end appearing @flash_end = 1.35 # Starts at @bg_2_appear_end @foe_disappear_start = 2.1 @foe_disappear_end = 2.3 # Also when screen starts turning white @fade_to_white_end = 2.5 @fade_to_black_start = 2.9 end def dispose_all # Dispose sprites @bg_1_sprite&.dispose @bg_2_sprite&.dispose @foe_sprite&.dispose @text_sprite&.dispose @black_sprite&.dispose # Dispose bitmaps @strobes_bitmap&.dispose @bg_1_bitmap&.dispose @bg_2_bitmap&.dispose @foe_bitmap&.dispose @black_bitmap&.dispose # Dispose viewport @flash_viewport&.dispose end def update_anim # Strobes scrolling if @sprites[0].visible @strobes_x -= Graphics.delta_s * STROBE_SCROLL_SPEED @strobes_x += @strobes_bitmap.width if @strobes_x <= -@strobes_bitmap.width @sprites.each_with_index { |spr, i| spr.x = @strobes_x + (i * @strobes_bitmap.width) } end if @timer >= @fade_to_black_start # Fade to black proportion = (@timer - @fade_to_black_start) / (@duration - @fade_to_black_start) @flash_viewport.color.alpha = 255 * (1 - proportion) elsif @timer >= @fade_to_white_end @flash_viewport.color.alpha = 255 # Ensure screen is white @black_sprite.visible = true # Make black overlay visible elsif @timer >= @foe_disappear_end @foe_sprite.visible = false # Ensure foe sprite has vanished @text_sprite.visible = false # Ensure name sprite has vanished # Slowly fade to white proportion = (@timer - @foe_disappear_end) / (@fade_to_white_end - @foe_disappear_end) @flash_viewport.color.alpha = 255 * proportion elsif @timer >= @foe_disappear_start # Slide foe sprite/name off-screen proportion = (@timer - @foe_disappear_start) / (@foe_disappear_end - @foe_disappear_start) start_x = Graphics.width / 2 @foe_sprite.x = start_x - ((@foe_bitmap.width + start_x) * proportion * proportion) @text_sprite.x = @foe_sprite.x - (Graphics.width / 2) elsif @timer >= @flash_end @flash_viewport.color.alpha = 0 # Ensure flash has ended elsif @timer >= @bg_2_appear_end @bg_2_sprite.opacity = 255 # Ensure BG 2 sprite is fully opaque @foe_sprite.x = Graphics.width / 2 # Ensure foe sprite is in the right place @text_sprite.x = 0 # Ensure name sprite is in the right place # Flash screen proportion = (@timer - @bg_2_appear_end) / (@flash_end - @bg_2_appear_end) @flash_viewport.color.alpha = 320 * (1 - proportion) elsif @timer >= @bg_2_appear_start # BG 2 sprite appears proportion = (@timer - @bg_2_appear_start) / (@bg_2_appear_end - @bg_2_appear_start) @bg_2_sprite.opacity = 255 * proportion # Foe sprite/name appear start_x = Graphics.width + (@foe_bitmap.width / 2) @foe_sprite.x = start_x + (((Graphics.width / 2) - start_x) * Math.sqrt(proportion)) @text_sprite.x = @foe_sprite.x - (Graphics.width / 2) @text_sprite.visible = true elsif @timer >= @bg_1_appear_end @bg_1_sprite.oy = Graphics.height / 2 @bg_1_sprite.src_rect.y = 0 @bg_1_sprite.src_rect.height = @bg_1_bitmap.height @sprites.each { |sprite| sprite.visible = false } # Hide strobes elsif @timer >= @bg_1_appear_start @flash_viewport.color.alpha = 0 # Ensure flash has ended # BG 1 sprite appears proportion = (@timer - @bg_1_appear_start) / (@bg_1_appear_end - @bg_1_appear_start) half_height = ((proportion * @bg_1_bitmap.height) / 2).to_i @bg_1_sprite.src_rect.height = half_height * 2 @bg_1_sprite.src_rect.y = (@bg_1_bitmap.height / 2) - half_height @bg_1_sprite.oy = half_height elsif @timer >= @strobe_appear_end @sprites.each { |sprite| sprite.opacity = 255 } # Ensure strobes are fully opaque # Flash the screen white proportion = (@timer - @strobe_appear_end) / (@bg_1_appear_start - @strobe_appear_end) if proportion >= 0.5 @flash_viewport.color.alpha = 320 * 2 * (1 - proportion) else @flash_viewport.color.alpha = 320 * proportion end else # Strobes fade in @sprites.each do |sprite| sprite.opacity = 255 * (@timer / @strobe_appear_end) end end end end end