From 41ce9309d736cf7c2d6b4df2ad5f4e79b5a0d992 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Fri, 20 Aug 2021 21:39:20 +0100 Subject: [PATCH] Refactored and improved transition animations --- .../003_Game processing/002_Scene_Map.rb | 8 +- Data/Scripts/009_Scenes/001_Transitions.rb | 2257 ++++++++--------- .../002_Overworld_BattleIntroAnim.rb | 3 +- .../001_Non-interactive UI/002_UI_Controls.rb | 4 +- .../001_Non-interactive UI/007_UI_Credits.rb | 6 +- Data/Scripts/019_Utilities/001_Utilities.rb | 6 +- Data/Scripts/999_Main/999_Main.rb | 2 +- 7 files changed, 1006 insertions(+), 1280 deletions(-) diff --git a/Data/Scripts/003_Game processing/002_Scene_Map.rb b/Data/Scripts/003_Game processing/002_Scene_Map.rb index dd8199317..7fc2be192 100644 --- a/Data/Scripts/003_Game processing/002_Scene_Map.rb +++ b/Data/Scripts/003_Game processing/002_Scene_Map.rb @@ -85,7 +85,7 @@ class Scene_Map createSpritesets if $game_temp.transition_processing $game_temp.transition_processing = false - Graphics.transition(20) + Graphics.transition end $game_map.autoplay Graphics.frame_reset @@ -172,7 +172,7 @@ class Scene_Map if $game_temp.transition_processing $game_temp.transition_processing = false if $game_temp.transition_name == "" - Graphics.transition(20) + Graphics.transition else Graphics.transition(40, "Graphics/Transitions/" + $game_temp.transition_name) end @@ -213,7 +213,7 @@ class Scene_Map def main createSpritesets - Graphics.transition(20) + Graphics.transition loop do Graphics.update Input.update @@ -223,7 +223,7 @@ class Scene_Map Graphics.freeze disposeSpritesets if $game_temp.to_title - Graphics.transition(20) + Graphics.transition Graphics.freeze end end diff --git a/Data/Scripts/009_Scenes/001_Transitions.rb b/Data/Scripts/009_Scenes/001_Transitions.rb index 478006e4c..b8b97275f 100644 --- a/Data/Scripts/009_Scenes/001_Transitions.rb +++ b/Data/Scripts/009_Scenes/001_Transitions.rb @@ -1,3 +1,6 @@ +#=============================================================================== +# +#=============================================================================== module Graphics @@transition = nil STOP_WHILE_TRANSITION = true @@ -12,6 +15,7 @@ module Graphics 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) @@ -21,9 +25,7 @@ module Graphics begin transition_KGC_SpecialTransition(duration, filename, vague) rescue Exception - if filename != "" - transition_KGC_SpecialTransition(duration, "", vague) - end + transition_KGC_SpecialTransition(duration, "", vague) if filename != "" end if STOP_WHILE_TRANSITION && !@_interrupt_transition while @@transition && !@@transition.disposed? @@ -34,13 +36,6 @@ module Graphics def self.update update_KGC_SpecialTransition -=begin - if Graphics.frame_count % 40 == 0 - count = 0 - ObjectSpace.each_object(Object) { |o| count += 1 } - echoln "Objects: #{count}" - end -=end @@transition.update if @@transition && !@@transition.disposed? @@transition = nil if @@transition && @@transition.disposed? end @@ -52,13 +47,14 @@ module Graphics @@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) + 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) @@ -95,367 +91,304 @@ module Graphics end end - - #=============================================================================== -# Screen transition classes +# Screen transition animation classes. #=============================================================================== module Transitions #============================================================================= - # + # A base class that all other screen transition animations inherit from. #============================================================================= - class BreakingGlass - def initialize(numframes) + class Transition_Base + DURATION = nil + + def initialize(duration, *args) @disposed = false - @numframes = numframes - @opacitychange = (numframes<=0) ? 255 : 255.0/numframes - cx = 6 - cy = 5 - @bitmap = Graphics.snap_to_bitmap - if !@bitmap + if duration <= 0 @disposed = true return end - width = @bitmap.width/cx - height = @bitmap.height/cy - @numtiles = cx*cy - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) + @duration = self.class::DURATION || duration + @parameters = args + @timer = 0.0 + initialize_bitmaps + return if disposed? + @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 @sprites = [] - @offset = [] - @y = [] - for i in 0...@numtiles - @sprites[i] = Sprite.new(@viewport) - @sprites[i].bitmap = @bitmap - @sprites[i].x = width*(i%cx) - @sprites[i].y = height*(i/cx) - @sprites[i].src_rect.set(@sprites[i].x,@sprites[i].y,width,height) - @offset[i] = (rand(100)+1)*3.0/100.0 - @y[i] = @sprites[i].y - end + initialize_sprites + @timings = [] + set_up_timings end - def disposed?; @disposed; end - - def dispose - if !disposed? - @bitmap.dispose - for i in 0...@numtiles - @sprites[i].visible = false - @sprites[i].dispose - end - @sprites.clear - @viewport.dispose if @viewport - @disposed = true - 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 update - return if disposed? - continue = false - for i in 0...@numtiles - @sprites[i].opacity -= @opacitychange - @y[i] += @offset[i] - @sprites[i].y = @y[i] - continue = true if @sprites[i].opacity>0 - end - self.dispose if !continue - end - end - - #============================================================================= - # - #============================================================================= - class ShrinkingPieces - def initialize(numframes,rotation) - @disposed = false - @rotation = rotation - @numframes = numframes - @opacitychange = (numframes<=0) ? 255 : 255.0/numframes - cx = 6 - cy = 5 - @bitmap = Graphics.snap_to_bitmap - if !@bitmap - @disposed = true - return - end - width = @bitmap.width/cx - height = @bitmap.height/cy - @numtiles = cx*cy - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprites = [] - for i in 0...@numtiles - @sprites[i] = Sprite.new(@viewport) - @sprites[i].bitmap = @bitmap - @sprites[i].ox = width/2 - @sprites[i].oy = height/2 - @sprites[i].x = width*(i%cx)+@sprites[i].ox - @sprites[i].y = height*(i/cx)+@sprites[i].oy - @sprites[i].src_rect.set(width*(i%cx),height*(i/cx),width,height) - end - end - - def disposed?; @disposed; end - - def dispose - if !disposed? - @bitmap.dispose - for i in 0...@numtiles - @sprites[i].visible = false - @sprites[i].dispose - end - @sprites.clear - @viewport.dispose if @viewport - @disposed = true - end - end - - def update - return if disposed? - continue = false - for i in 0...@numtiles - @sprites[i].opacity -= @opacitychange - if @rotation - @sprites[i].angle += 40 - @sprites[i].angle %= 360 - end - @sprites[i].zoom_x = @sprites[i].opacity/255.0 - @sprites[i].zoom_y = @sprites[i].opacity/255.0 - continue = true if @sprites[i].opacity>0 - end - self.dispose if !continue - end - end - - #============================================================================= - # - #============================================================================= - class SplashTransition - SPLASH_SIZE = 32 - - def initialize(numframes,vague=9.6) - @duration = numframes - @numframes = numframes - @splash_dir = [] - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @buffer = Graphics.snap_to_bitmap - if !@buffer - @disposed = true - return - end - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprite = Sprite.new(@viewport) - @sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height) - size = SPLASH_SIZE - size = [size,1].max - cells = Graphics.width*Graphics.height/(size**2) - rows = Graphics.width/size - rect = Rect.new(0,0,size,size) - mag = 40.0/@numframes - cells.times { |i| - rect.x = i%rows*size - rect.y = i/rows*size - x = rect.x/size-(rows>>1) - y = rect.y/size-((cells/rows)>>1) - r = Math.sqrt(x**2+y**2)/vague - @splash_dir[i] = [] - if r!=0 - @splash_dir[i][0] = x/r - @splash_dir[i][1] = y/r - else - @splash_dir[i][0] = (x!= 0) ? x*1.5 : pmrand*vague - @splash_dir[i][1] = (y!= 0) ? y*1.5 : pmrand*vague - end - @splash_dir[i][0] += (rand-0.5)*vague - @splash_dir[i][1] += (rand-0.5)*vague - @splash_dir[i][0] *= mag - @splash_dir[i][1] *= mag - } - @sprite.bitmap.blt(0,0,@buffer,@buffer.rect) - end - - def disposed?; @disposed; end - def dispose return if disposed? - @buffer.dispose if @buffer - @buffer = nil - @sprite.visible = false - @sprite.bitmap.dispose - @sprite.dispose + dispose_all + @sprites.each { |s| s.dispose if s } + @sprites.clear @viewport.dispose if @viewport @disposed = true end + def disposed?; return @disposed; end + def update return if disposed? - if @duration==0 + @timer += Graphics.delta_s + if @timer >= @duration dispose - else - size = SPLASH_SIZE - cells = Graphics.width*Graphics.height/(size**2) - rows = Graphics.width/size - rect = Rect.new(0,0,size,size) - buffer = @buffer - sprite = @sprite - phase = @numframes-@duration - sprite.bitmap.clear - cells.times { |i| - rect.x = (i%rows)*size - rect.y = (i/rows)*size - dx = rect.x+@splash_dir[i][0]*phase - dy = rect.y+@splash_dir[i][1]*phase - sprite.bitmap.blt(dx,dy,buffer,rect) - } - sprite.opacity = 384*@duration/@numframes - @duration -= 1 + 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_bitmaps + @buffer = Graphics.snap_to_bitmap + dispose if !@buffer + end + + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprites + sprite_width = @buffer.width / NUM_SPRITES_X + sprite_height = @buffer.height / NUM_SPRITES_Y + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + idx_sprite = j * NUM_SPRITES_X + i + @sprites[idx_sprite] = new_sprite(i * sprite_width, j * sprite_height, @buffer) + @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 = [] + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + 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 dispose_all + @black_sprite.dispose if @black_sprite + @buffer.dispose if @buffer + 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_bitmaps + @buffer = Graphics.snap_to_bitmap + dispose if !@buffer + end + + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprites + sprite_width = @buffer.width / NUM_SPRITES_X + sprite_height = @buffer.height / NUM_SPRITES_Y + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + idx_sprite = j * NUM_SPRITES_X + i + @sprites[idx_sprite] = new_sprite((i + 0.5) * sprite_width, (j + 0.5) * sprite_height, + @buffer, 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 dispose_all + @black_sprite.dispose if @black_sprite + @buffer.dispose if @buffer + end + + def update_anim + proportion = @timer / @duration + @sprites.each_with_index do |sprite, i| + sprite.zoom_x = 1.0 * (1 - proportion) + 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_bitmaps + @buffer = Graphics.snap_to_bitmap + dispose if !@buffer + end + + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprites + sprite_width = @buffer.width / NUM_SPRITES_X + sprite_height = @buffer.height / NUM_SPRITES_Y + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + idx_sprite = j * NUM_SPRITES_X + i + @sprites[idx_sprite] = new_sprite((i + 0.5) * sprite_width, (j + 0.5) * sprite_height, + @buffer, 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 + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + 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 dispose_all + @black_sprite.dispose if @black_sprite + @buffer.dispose if @buffer + 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 pmrand - return (rand(2)==0) ? 1 : -1 + def rand_sign + return (rand(2) == 0) ? 1 : -1 end end #============================================================================= # #============================================================================= - class RandomStripeTransition - RAND_STRIPE_SIZE = 2 + class RandomStripeTransition < Transition_Base + STRIPE_WIDTH = 2 - def initialize(numframes,direction) - @duration = numframes - @numframes = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end + def initialize_bitmaps @buffer = Graphics.snap_to_bitmap - if !@buffer - @disposed = true - return + dispose if !@buffer + end + + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprites + if @parameters[0] == 0 # Vertical stripes + sprite_width = STRIPE_WIDTH + sprite_height = @buffer.height + num_stripes_x = @buffer.width / STRIPE_WIDTH + num_stripes_y = 1 + else # Horizontal stripes + sprite_width = @buffer.width + sprite_height = STRIPE_WIDTH + num_stripes_x = 1 + num_stripes_y = @buffer.height / STRIPE_WIDTH end - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprite = Sprite.new(@viewport) - @sprite.bitmap = Bitmap.new(Graphics.width,Graphics.height) - ########## - @direction = direction - size = RAND_STRIPE_SIZE - bands = ((@direction==0) ? Graphics.width : Graphics.height)/size - @rand_stripe_deleted = [] - @rand_stripe_deleted_count = 0 - ary = (0...bands).to_a - @rand_stripe_index_array = ary.sort_by { rand } - ########## - @sprite.bitmap.blt(0,0,@buffer,@buffer.rect) - end - - def disposed?; @disposed; end - - def dispose - return if disposed? - @buffer.dispose if @buffer - @buffer = nil - @sprite.visible = false - @sprite.bitmap.dispose - @sprite.dispose - @viewport.dispose if @viewport - @disposed = true - end - - def update - return if disposed? - if @duration==0 - dispose - else - dir = @direction - size = RAND_STRIPE_SIZE - bands = ((dir==0) ? Graphics.width : Graphics.height)/size - rect = Rect.new(0,0,(dir==0) ? size : Graphics.width,(dir==0) ? Graphics.height : size) - buffer = @buffer - sprite = @sprite - count = (bands-bands*@duration/@numframes)-@rand_stripe_deleted_count - while count > 0 - @rand_stripe_deleted[@rand_stripe_index_array.pop] = true - @rand_stripe_deleted_count += 1 - count -= 1 + for j in 0...num_stripes_y + for i in 0...num_stripes_x + idx_sprite = j * num_stripes_x + i + @sprites[idx_sprite] = new_sprite(i * sprite_width, j * sprite_height, @buffer) + @sprites[idx_sprite].src_rect.set(i * sprite_width, j * sprite_height, sprite_width, sprite_height) end - sprite.bitmap.clear - bands.to_i.times { |i| - unless @rand_stripe_deleted[i] - if dir==0 - rect.x = i*size - sprite.bitmap.blt(rect.x,0,buffer,rect) - else - rect.y = i*size - sprite.bitmap.blt(0,rect.y,buffer,rect) - end - end - } - @duration -= 1 end end - end - #============================================================================= - # - #============================================================================= - class ZoomInTransition - def initialize(numframes) - @duration = numframes - @numframes = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return + def set_up_timings + for i in 0...@sprites.length + @timings[i] = @duration * i / @sprites.length end - @buffer = Graphics.snap_to_bitmap - if !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @sprite = Sprite.new(@viewport) - @sprite.bitmap = @buffer - @sprite.ox = @width/2 - @sprite.oy = @height/2 - @sprite.x = @width/2 - @sprite.y = @height/2 + @timings.shuffle! end - def disposed?; @disposed; end - - def dispose - return if disposed? + def dispose_all + @black_sprite.dispose if @black_sprite @buffer.dispose if @buffer - @buffer = nil - @sprite.dispose if @sprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - @sprite.zoom_x += 0.2 - @sprite.zoom_y += 0.2 - @sprite.opacity = (@duration-1)*255/@numframes - @duration -= 1 + 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 @@ -463,122 +396,70 @@ module Transitions #============================================================================= # #============================================================================= - class ScrollScreen - def initialize(numframes,direction) - @numframes = numframes - @duration = numframes - @dir = direction - @disposed = false - if @numframes<=0 - @disposed = true - return - end + class ZoomInTransition < Transition_Base + def initialize_bitmaps @buffer = Graphics.snap_to_bitmap - if !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @sprite = Sprite.new(@viewport) - @sprite.bitmap = @buffer + @disposed = true if !@buffer end - def disposed?; @disposed; end + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprite + @sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @buffer, + @buffer.width / 2, @buffer.height / 2) + @sprite.z = 1 + end - def dispose - return if disposed? - @buffer.dispose if @buffer - @buffer = nil + def dispose_all + # Dispose sprites @sprite.dispose if @sprite - @viewport.dispose if @viewport - @disposed = true + @black_sprite.dispose if @black_sprite + # Dispose bitmaps + @buffer.dispose if @buffer end - def update - return if disposed? - if @duration==0 - dispose - else - case @dir - when 1 # down left - @sprite.y += (@height/@numframes) - @sprite.x -= (@width/@numframes) - when 2 # down - @sprite.y += (@height/@numframes) - when 3 # down right - @sprite.y += (@height/@numframes) - @sprite.x += (@width/@numframes) - when 4 # left - @sprite.x -= (@width/@numframes) - when 6 # right - @sprite.x += (@width/@numframes) - when 7 # up left - @sprite.y -= (@height/@numframes) - @sprite.x -= (@width/@numframes) - when 8 # up - @sprite.y -= (@height/@numframes) - when 9 # up right - @sprite.y -= (@height/@numframes) - @sprite.x += (@width/@numframes) - end - @duration -= 1 - end + def update_anim + proportion = @timer / @duration + @sprite.zoom_x = 1.0 + 7.0 * proportion + @sprite.zoom_y = @sprite.zoom_x + @sprite.opacity = 255 * (1 - proportion) end end #============================================================================= # #============================================================================= - class MosaicTransition - def initialize(numframes) - @duration = numframes - @numframes = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end + class ScrollScreen < Transition_Base + def initialize_bitmaps @buffer = Graphics.snap_to_bitmap - if !@buffer - @disposed = true - return - end - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprite = Sprite.new(@viewport) - @sprite.bitmap = @buffer - @bitmapclone = @buffer.clone - @bitmapclone2 = @buffer.clone + dispose if !@buffer end - def disposed?; @disposed; end + def initialize_sprites + # Black background + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + # Overworld sprite + @overworld_sprite = new_sprite(0, 0, @buffer) + end - def dispose - return if disposed? + def dispose_all + # Dispose sprites + @black_sprite.dispose if @black_sprite + @overworld_sprite.dispose if @overworld_sprite + # Dispose bitmaps @buffer.dispose if @buffer - @buffer = nil - @sprite.dispose if @sprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - @bitmapclone2.stretch_blt( - Rect.new(0,0,@buffer.width*@duration/@numframes,@buffer.height*@duration/@numframes), - @bitmapclone, - Rect.new(0,0,@buffer.width,@buffer.height)) - @buffer.stretch_blt( - Rect.new(0,0,@buffer.width,@buffer.height), - @bitmapclone2, - Rect.new(0,0,@buffer.width*@duration/@numframes,@buffer.height*@duration/@numframes)) - @duration -= 1 + 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 @@ -586,156 +467,151 @@ module Transitions #============================================================================= # #============================================================================= - class FadeToBlack - def initialize(numframes) - @duration = numframes - @numframes = numframes - @disposed = false - if @duration<=0 - @disposed = true - return + class MosaicTransition < Transition_Base + MAX_PIXELLATION_FACTOR = 16 + + def initialize_bitmaps + @buffer = Graphics.snap_to_bitmap # Used by the overworld sprite + dispose if !@buffer + @buffer_original = @buffer.clone # Copy of original, never changes + @buffer_temp = @buffer.clone # "Clipboard" holding shrunken overworld + end + + def initialize_sprites + @overworld_sprite = new_sprite(0, 0, @buffer) + # Black sprite (fades in at end) + @black_sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @black_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) + @black_sprite.z = 1 + @black_sprite.opacity = 0 + end + + def set_up_timings + @start_black_fade = @duration * 0.9 + end + + def dispose_all + # Dispose sprites + @overworld_sprite.dispose if @overworld_sprite + @black_sprite.dispose if @black_sprite + # Dispose bitmaps + @buffer.dispose if @buffer + @buffer_original.dispose if @buffer_original + @buffer_temp.dispose if @buffer_temp + end + + def update_anim + proportion = @timer / @duration + inv_proportion = 1 / (1 + proportion * (MAX_PIXELLATION_FACTOR - 1)) + new_size_rect = Rect.new(0, 0, @buffer.width * inv_proportion, @buffer.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, @buffer.width, @buffer.height)) + # Take shrunken area from buffer_temp and stretch it into buffer + @buffer.stretch_blt(Rect.new(0, 0, @buffer.width, @buffer.height), + @buffer_temp, new_size_rect) + if @timer >= @start_black_fade + @black_sprite.opacity = 255 * (@timer - @start_black_fade) / (@duration - @start_black_fade) end - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprite = BitmapSprite.new(Graphics.width,Graphics.height,@viewport) - @sprite.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0)) + end + end + + #============================================================================= + # + #============================================================================= + class FadeToBlack < Transition_Base + def initialize_sprites + @sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) @sprite.opacity = 0 end - def disposed?; @disposed; end - - def dispose - return if disposed? + def dispose_all @sprite.dispose if @sprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - @sprite.opacity = (@numframes - @duration + 1) * 255 / @numframes - @duration -= 1 - end + def update_anim + @sprite.opacity = (@timer / @duration) * 255 end end #============================================================================= # #============================================================================= - class FadeFromBlack - def initialize(numframes) - @duration = numframes - @numframes = numframes - @disposed = false - if @duration<=0 - @disposed = true - return - end - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprite = BitmapSprite.new(Graphics.width,Graphics.height,@viewport) - @sprite.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0)) + class FadeFromBlack < Transition_Base + def initialize_sprites + @sprite = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0)) @sprite.opacity = 255 end - def disposed?; @disposed; end - - def dispose - return if disposed? + def dispose_all @sprite.dispose if @sprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - @sprite.opacity = (@duration-1)*255/@numframes - @duration -= 1 - end + def update_anim + @sprite.opacity = (@duration - @timer) * 255 / @duration end end #============================================================================= # HGSS wild outdoor #============================================================================= - class SnakeSquares - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - @bitmap = RPG::Cache.transition("black_square") - if !@bitmap + 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 - width = @bitmap.width - height = @bitmap.height - cx = Graphics.width/width # 8 - cy = Graphics.height/height # 6 - @numtiles = cx*cy - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprites = [] - @frame = [] - @addzoom = 0.125*50/@numframes - for i in 0...cy - for j in 0...cx - k = i*cx+j - x = width*(j%cx) - x = (cx-1)*width-x if (i<3 && i%2==1) || (i>=3 && i%2==0) - @sprites[k] = Sprite.new(@viewport) - @sprites[k].x = x+width/2 - @sprites[k].y = height*i - @sprites[k].ox = width/2 - @sprites[k].visible = false - @sprites[k].bitmap = @bitmap - if k>=@numtiles/2 - @frame[k] = 2*(@numtiles-k-1)*(@numframes-1/@addzoom)/50 - else - @frame[k] = 2*k*(@numframes-1/@addzoom)/50 - 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 + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + idx_sprite = j * NUM_SPRITES_X + i + sprite_x = ((j.even?) ? i : (NUM_SPRITES_X - i - 1)) * @black_bitmap.width + @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 disposed?; @disposed; end - - def dispose - if !disposed? - @bitmap.dispose - for i in 0...@numtiles - if @sprites[i] - @sprites[i].visible = false - @sprites[i].dispose - end + def set_up_timings + time_between_zooms = (@duration - TIME_TO_ZOOM) * 2 / (TOTAL_SPRITES - 1) + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + 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 - @sprites.clear - @viewport.dispose if @viewport - @disposed = true end end - def update - return if disposed? - if @duration==0 - dispose - else - count = @numframes-@duration - for i in 0...@numtiles - if @frame[i]=count - @sprites[i].visible = true - @sprites[i].zoom_x = @addzoom*(count-@frame[i]) - @sprites[i].zoom_x = 1.0 if @sprites[i].zoom_x>1.0 - 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 - @duration -= 1 end end @@ -744,491 +620,425 @@ module Transitions # HGSS wild indoor night (origin=3) # HGSS wild cave (origin=3) #============================================================================= - class DiagonalBubble - def initialize(numframes,origin=0) - @numframes = numframes - @duration = numframes - @disposed = false + 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 - width = @bitmap.width - height = @bitmap.height - cx = Graphics.width/width # 8 - cy = Graphics.height/height # 6 - @numtiles = cx*cy - @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) - @viewport.z = 99999 - @sprites = [] - @frame = [] - # 1.2, 0.6 and 0.8 determined by trigonometry of default screen size - l = 1.2*Graphics.width/(@numtiles-8) - for i in 0...cy - for j in 0...cx - k = i*cx+j - @sprites[k] = Sprite.new(@viewport) - @sprites[k].x = width*j+width/2 - @sprites[k].y = height*i+height/2 - @sprites[k].ox = width/2 - @sprites[k].oy = height/2 - @sprites[k].visible = false - @sprites[k].bitmap = @bitmap - case origin - when 1 then k = i*cx+(cx-1-j) # Top right - when 2 then k = @numtiles-1-(i*cx+(cx-1-j)) # Bottom left - when 3 then k = @numtiles-1-k # Bottom right - end - @frame[k] = ((0.6*j*width+0.8*i*height)*(@numframes/50.0)/l).floor - end - end - @addzoom = 0.125*50/@numframes + @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 disposed?; @disposed; end - - def dispose - if !disposed? - @bitmap.dispose - for i in 0...@numtiles - if @sprites[i] - @sprites[i].visible = false - @sprites[i].dispose - end + def initialize_sprites + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + 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 - @sprites.clear - @viewport.dispose if @viewport - @disposed = true end end - def update - return if disposed? - if @duration==0 - dispose - else - count = @numframes-@duration - for i in 0...@numtiles - if @frame[i]=count - @sprites[i].visible = true - @sprites[i].zoom_x = @addzoom*(count-@frame[i]) - @sprites[i].zoom_x = 1.0 if @sprites[i].zoom_x>1.0 - @sprites[i].zoom_y = @sprites[i].zoom_x + def set_up_timings + time_between_zooms = (@duration - TIME_TO_ZOOM) * 2 / (TOTAL_SPRITES - 1) + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + idx_from_start = j * NUM_SPRITES_X + i # Top left -> bottom right + case @parameters[0] || 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[i].visible = true + size = (@timer - @timings[i]) / TIME_TO_ZOOM + sprite.zoom_x = @zoom_x_target * size + sprite.zoom_y = @zoom_y_target * size + if size >= 1.0 + sprite.zoom_x = @zoom_x_target + sprite.zoom_y = @zoom_y_target + @timings[i] = -1 end end - @duration -= 1 end end #============================================================================= # HGSS wild water #============================================================================= - class RisingSplash - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @bubblebitmap = RPG::Cache.transition("water_1") - @splashbitmap = RPG::Cache.transition("water_2") - @blackbitmap = RPG::Cache.transition("black_half") - @buffer = Graphics.snap_to_bitmap - if !@bubblebitmap || !@splashbitmap || !@blackbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @rearsprite = Sprite.new(@viewport) - @rearsprite.z = 1 - @rearsprite.zoom_y = 2.0 - @rearsprite.bitmap = @blackbitmap - @bgsprites = [] - rect = Rect.new(0,0,@width,2) - for i in 0...@height/2 - @bgsprites[i] = Sprite.new(@viewport) - @bgsprites[i].y = i*2 - @bgsprites[i].z = 2 - @bgsprites[i].bitmap = @buffer - rect.y = i*2 - @bgsprites[i].src_rect = rect - end - @bubblesprite = Sprite.new(@viewport) - @bubblesprite.y = @height - @bubblesprite.z = 3 - @bubblesprite.bitmap = @bubblebitmap - @splashsprite = Sprite.new(@viewport) - @splashsprite.y = @height - @splashsprite.z = 4 - @splashsprite.bitmap = @splashbitmap - @blacksprite = Sprite.new(@viewport) - @blacksprite.y = @height - @blacksprite.z = 5 - @blacksprite.zoom_y = 2.0 - @blacksprite.bitmap = @blackbitmap - @bubblesuby = @height*2/@numframes - @splashsuby = @bubblesuby*2 - @blacksuby = @height/(@numframes*0.1).floor - @angmult = 2/(@numframes/50.0) + 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") + @buffer = Graphics.snap_to_bitmap + dispose if !@bubble_bitmap || !@splash_bitmap || !@black_bitmap || !@buffer end - def disposed?; @disposed; end + def initialize_sprites + # Black background + @black_bg_sprite = new_sprite(0, 0, @black_bitmap) + @black_bg_sprite.z = 1 + @black_bg_sprite.zoom_y = 2.0 + # Overworld strips (they go all wavy) + rect = Rect.new(0, 0, Graphics.width, 2) + for i in 0...Graphics.height / 2 + @sprites[i] = new_sprite(0, i * 2, @buffer) + @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 dispose - return if disposed? + def set_up_timings + @splash_rising_start = @duration * 0.5 + @black_rising_start = @duration * 0.9 + end + + def dispose_all + # Dispose sprites + @black_bg_sprite.dispose if @black_bg_sprite + @bubbles_sprite.dispose if @bubbles_sprite + @splash_sprite.dispose if @splash_sprite + @black_sprite.dispose if @black_sprite + # Dispose bitmaps + @bubble_bitmap.dispose if @bubble_bitmap + @splash_bitmap.dispose if @splash_bitmap + @black_bitmap.dispose if @black_bitmap @buffer.dispose if @buffer - @buffer = nil - @bubblebitmap.dispose if @bubblebitmap - @bubblebitmap = nil - @splashbitmap.dispose if @splashbitmap - @splashbitmap = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @rearsprite.dispose if @rearsprite - for i in @bgsprites; i.dispose if i; end - @bgsprites.clear - @bubblesprite.dispose if @bubblesprite - @splashsprite.dispose if @splashsprite - @blacksprite.dispose if @blacksprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - angadd = (@numframes-@duration)*@angmult - amp = 6*angadd/8; amp = 6 if amp>6 - for i in 0...@bgsprites.length - @bgsprites[i].x = amp*Math.sin((i+angadd)*Math::PI/10) - end - @bubblesprite.x = (@width-@bubblebitmap.width)/2 - @bubblesprite.x -= 32*Math.sin((@numframes-@duration)/(@numframes/50)*3*Math::PI/60) - @bubblesprite.y -= @bubblesuby - if @duration<@numframes*0.5 - @splashsprite.y -= @splashsuby - end - if @duration<@numframes*0.1 - @blacksprite.y -= @blacksuby - @blacksprite.y = 0 if @blacksprite.y<0 - 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 - @duration -= 1 end end #============================================================================= # HGSS trainer outdoor day #============================================================================= - class TwoBallPass - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @blackbitmap = RPG::Cache.transition("black_half") - @ballbitmap = RPG::Cache.transition("ball_small") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @bgsprite = Sprite.new(@viewport) - @bgsprite.x = @width/2 - @bgsprite.y = @height/2 - @bgsprite.ox = @width/2 - @bgsprite.oy = @height/2 - @bgsprite.bitmap = @buffer - @blacksprites = [] - @ballsprites = [] + class TwoBallPass < Transition_Base + DURATION = 1.0 + + def initialize_bitmaps + @black_bitmap = RPG::Cache.transition("black_half") + @ball_bitmap = RPG::Cache.transition("ball_small") + @buffer = Graphics.snap_to_bitmap + dispose if !@black_bitmap || !@ball_bitmap || !@buffer + end + + def initialize_sprites + # Sprite showing the overworld (it zooms in) + @overworld_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @buffer, + @buffer.width / 2, @buffer.height / 2) + # Balls that roll across the screen + @ball_sprites = [] for i in 0...2 - @blacksprites[i] = Sprite.new(@viewport) - @blacksprites[i].x = (1-i*2)*@width - @blacksprites[i].y = i*@height/2 - @blacksprites[i].z = 1 - @blacksprites[i].bitmap = @blackbitmap - @ballsprites[i] = Sprite.new(@viewport) - @ballsprites[i].x = (1-i)*@width + (1-i*2)*@ballbitmap.width/2 - @ballsprites[i].y = @height/2 + (i*2-1)*@ballbitmap.height/2 - @ballsprites[i].z = 2 - @ballsprites[i].ox = @ballbitmap.width/2 - @ballsprites[i].oy = @ballbitmap.height/2 - @ballsprites[i].bitmap = @ballbitmap + 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 - @blacksprites[2] = Sprite.new(@viewport) - @blacksprites[2].y = @height/2 - @blacksprites[2].z = 1 - @blacksprites[2].oy = @height/4 - @blacksprites[2].zoom_y = 0.0 - @blacksprites[2].bitmap = @blackbitmap - @addxmult = 2.0*@width/((@numframes*0.6)**2) - @addzoom = 0.02*50/@numframes + # Black foreground sprites + for i in 0...2 + @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 disposed?; @disposed; 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 - return if disposed? + def dispose_all + # Dispose sprites + @overworld_sprite.dispose if @overworld_sprite + if @ball_sprites + @ball_sprites.each { |s| s.dispose if s } + @ball_sprites.clear + end + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - @bgsprite.dispose if @bgsprite - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - for i in @ballsprites; i.dispose if i; end - @ballsprites.clear - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - elsif @duration>=@numframes*0.6 - for i in 0...2 - @ballsprites[i].x += (2*i-1)*((@width+@ballbitmap.width)/(0.4*@numframes)) - @ballsprites[i].angle += (2*i-1)*(360.0/(0.2*@numframes)) + 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 - addx = (@numframes*0.6-@duration)*@addxmult - for i in 0...2 - @bgsprite.zoom_x += @addzoom - @bgsprite.zoom_y += @addzoom - @blacksprites[i].x += (2*i-1)*addx + 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 - @blacksprites[2].zoom_y += 2*addx/@width - @blacksprites[0].x = 0 if @blacksprites[0].x<0 - @blacksprites[1].x = 0 if @blacksprites[1].x>0 + # 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 - @duration -= 1 end end #============================================================================= # HGSS trainer outdoor night #============================================================================= - class SpinBallSplit - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @blackbitmap = RPG::Cache.transition("black_half") - @ballbitmap = RPG::Cache.transition("ball_large") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @bgsprites = [] - @blacksprites = [] - @ballsprites = [] + class SpinBallSplit < Transition_Base + DURATION = 1.0 + + def initialize_bitmaps + @black_bitmap = RPG::Cache.transition("black_half") + @ball_bitmap = RPG::Cache.transition("ball_large") + @buffer = Graphics.snap_to_bitmap + dispose if !@black_bitmap || !@ball_bitmap || !@buffer + end + + def initialize_sprites + @overworld_sprites = [] + @black_sprites = [] + @ball_sprites = [] for i in 0...2 - @bgsprites[i] = Sprite.new(@viewport) - @bgsprites[i].x = @width/2 - @bgsprites[i].y = @height/2 - @bgsprites[i].ox = @width/2 - @bgsprites[i].oy = (1-i)*@height/2 - @bgsprites[i].bitmap = @buffer - @bgsprites[i].src_rect.set(0,i*@height/2,@width,@height/2) - @blacksprites[i] = Sprite.new(@viewport) - @blacksprites[i].x = (1-i*2)*@width - @blacksprites[i].y = i*@height/2 - @blacksprites[i].z = 1 - @blacksprites[i].bitmap = @blackbitmap - @ballsprites[i] = Sprite.new(@viewport) - @ballsprites[i].x = @width/2 - @ballsprites[i].y = @height/2 - @ballsprites[i].z = 2 - @ballsprites[i].ox = @ballbitmap.width/2 - @ballsprites[i].oy = (1-i)*@ballbitmap.height/2 - @ballsprites[i].zoom_x = 0.0 - @ballsprites[i].zoom_y = 0.0 - @ballsprites[i].bitmap = @ballbitmap + # Overworld sprites (they split apart) + @overworld_sprites[i] = new_sprite(Graphics.width / 2, Graphics.height / 2, @buffer, + 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 - @addxmult = 2.0*@width/((@numframes*0.5)**2) - @addzoom = 0.02*50/@numframes end - def disposed?; @disposed; end + def set_up_timings + @ball_spin_end = @duration * 0.4 + @slide_start = @duration * 0.5 + end - def dispose - return if disposed? + def dispose_all + # Dispose sprites + if @overworld_sprites + @overworld_sprites.each { |s| s.dispose if s } + @overworld_sprites.clear + end + if @black_sprites + @black_sprites.each { |s| s.dispose if s } + @black_sprites.clear + end + if @ball_sprites + @ball_sprites.each { |s| s.dispose if s } + @ball_sprites.clear + end + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - for i in @bgsprites; i.dispose if i; end - @bgsprites.clear - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - for i in @ballsprites; i.dispose if i; end - @ballsprites.clear - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - elsif @duration>=@numframes*0.6 - if @ballsprites[0].zoom_x<1.0 - @ballsprites[0].zoom_x += (1.0/(0.4*@numframes)) - @ballsprites[0].zoom_y += (1.0/(0.4*@numframes)) - @ballsprites[0].angle -= (360.0/(0.4*@numframes)) - if @ballsprites[0].zoom_x>=1.0 - for i in 0...2 - @ballsprites[i].src_rect.set(0,i*@ballbitmap.height/2, - @ballbitmap.width,@ballbitmap.height/2) - @ballsprites[i].zoom_x = @ballsprites[i].zoom_y = 1.0 - @ballsprites[i].angle = 0.0 - 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 - # Gap between 0.6*@numframes and 0.5*@numframes - elsif @duration<@numframes*0.5 - addx = (@numframes*0.5-@duration)*@addxmult - for i in 0...2 - @bgsprites[i].x += (2*i-1)*addx - @bgsprites[i].zoom_x += @addzoom - @bgsprites[i].zoom_y += @addzoom - @blacksprites[i].x += (2*i-1)*addx - @ballsprites[i].x += (2*i-1)*addx + 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 - @blacksprites[0].x = 0 if @blacksprites[0].x<0 - @blacksprites[1].x = 0 if @blacksprites[1].x>0 end - @duration -= 1 end end #============================================================================= # HGSS trainer indoor day #============================================================================= - class ThreeBallDown - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true + 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") + @buffer = Graphics.snap_to_bitmap + if !@black_bitmap || !@ball_bitmap || !@buffer + dispose return end - @blackbitmap = RPG::Cache.transition("black_square") - @ballbitmap = RPG::Cache.transition("ball_small") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - cx = Graphics.width/@blackbitmap.width # 8 - cy = Graphics.height/@blackbitmap.height # 6 - @numtiles = cx*cy - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @bgsprite = Sprite.new(@viewport) - @bgsprite.x = @width/2 - @bgsprite.y = @height/2 - @bgsprite.ox = @width/2 - @bgsprite.oy = @height/2 - @bgsprite.bitmap = @buffer - @frame = [] - @blacksprites = [] - for i in 0...cy - for j in 0...cx - k = i*cx+j - @blacksprites[k] = Sprite.new(@viewport) - @blacksprites[k].x = @blackbitmap.width*j - @blacksprites[k].y = @blackbitmap.height*i - @blacksprites[k].visible = false - @blacksprites[k].bitmap = @blackbitmap - @frame[k] = (((cy-i-1)*8+[0,4,1,6,7,2,5,3][j])*(@numframes*0.75)/@numtiles).floor + @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 + # Sprite showing the overworld (it zooms in) + @overworld_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @buffer, + Graphics.width / 2, Graphics.height / 2) + # Black squares + for j in 0...NUM_SPRITES_Y + for i in 0...NUM_SPRITES_X + 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 - @ballsprites = [] + # Falling balls + @ball_sprites = [] for i in 0...3 - @ballsprites[i] = Sprite.new(@viewport) - @ballsprites[i].x = 96+i*160 - @ballsprites[i].y = -@ballbitmap.height-[400,0,100][i] - @ballsprites[i].z = 2 - @ballsprites[i].ox = @ballbitmap.width/2 - @ballsprites[i].oy = @ballbitmap.height/2 - @ballsprites[i].bitmap = @ballbitmap + @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 - @addyball = (@height+400+@ballbitmap.height*2)/(0.25*@numframes) - @addangle = 1.5*360/(0.25*@numframes) - @addzoom = 0.02*50/@numframes end - def disposed?; @disposed; 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 + for j in 0...NUM_SPRITES_Y + row_offset = NUM_SPRITES_Y - j - 1 + for i in 0...NUM_SPRITES_X + 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 - return if disposed? + def dispose_all + # Dispose sprites + @overworld_sprite.dispose if @overworld_sprite + if @ball_sprites + @ball_sprites.each { |s| s.dispose if s } + @ball_sprites.clear + end + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - @bgsprite.dispose if @bgsprite - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - for i in @ballsprites; i.dispose if i; end - @ballsprites.clear - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - elsif @duration>=@numframes*0.75 - for i in 0...@ballsprites.length - @ballsprites[i].y += @addyball - @ballsprites[i].angle -= @addangle*([1,-1][(i==2) ? 1 : 0]) + 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 - count = (@numframes*0.75).floor-@duration - for i in 0...@numtiles - @blacksprites[i].visible = true if @frame[i]<=count + # Black squares appear + @timings.each_with_index do |timing, i| + next if timing < 0 || @timer < timing + @sprites[i].visible = true + @timings[i] = -1 end - @bgsprite.zoom_x += @addzoom - @bgsprite.zoom_y += @addzoom + # 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 - @duration -= 1 end end @@ -1236,392 +1046,307 @@ module Transitions # HGSS trainer indoor night # HGSS trainer cave #============================================================================= - class BallDown - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @blackbitmap = RPG::Cache.transition("black_half") - @curvebitmap = RPG::Cache.transition("black_curve") - @ballbitmap = RPG::Cache.transition("ball_small") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@curvebitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @bgsprite = Sprite.new(@viewport) - @bgsprite.x = @width/2 - @bgsprite.y = @height/2 - @bgsprite.ox = @width/2 - @bgsprite.oy = @height/2 - @bgsprite.bitmap = @buffer - @blacksprites = [] - @blacksprites[0] = Sprite.new(@viewport) - @blacksprites[0].y = -@curvebitmap.height - @blacksprites[0].z = 1 - @blacksprites[0].oy = @blackbitmap.height - @blacksprites[0].zoom_y = 2.0 - @blacksprites[0].bitmap = @blackbitmap - @blacksprites[1] = Sprite.new(@viewport) - @blacksprites[1].y = -@curvebitmap.height - @blacksprites[1].z = 1 - @blacksprites[1].bitmap = @curvebitmap - @ballsprite = Sprite.new(@viewport) - @ballsprite.x = @width/2 - @ballsprite.y = -@ballbitmap.height/2 - @ballsprite.z = 2 - @ballsprite.ox = @ballbitmap.width/2 - @ballsprite.oy = @ballbitmap.height/2 - @ballsprite.zoom_x = 0.25 - @ballsprite.zoom_y = 0.25 - @ballsprite.bitmap = @ballbitmap - @addyball = (@height+@ballbitmap.height*2.5)/(0.5*@numframes) - @addangle = 1.5*360/(0.5*@numframes) - @addzoomball = 2.5/(0.5*@numframes) - @addy = (@height+@curvebitmap.height)/(@numframes*0.5) - @addzoom = 0.02*50/@numframes + 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") + @buffer = Graphics.snap_to_bitmap + dispose if !@black_bitmap || !@curve_bitmap || !@ball_bitmap || !@buffer end - def disposed?; @disposed; end + def initialize_sprites + # Sprite showing the overworld (it zooms in) + @overworld_sprite = new_sprite(Graphics.width / 2, Graphics.height / 2, @buffer, + @buffer.width / 2, @buffer.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 dispose - return if disposed? + def set_up_timings + @ball_appear_end = @duration * 0.7 + end + + def dispose_all + # Dispose sprites + @overworld_sprite.dispose if @overworld_sprite + @ball_sprite.dispose if @ball_sprite + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @curve_bitmap.dispose if @curve_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @curvebitmap.dispose if @curvebitmap - @curvebitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - @bgsprite.dispose if @bgsprite - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - @ballsprite.dispose - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - elsif @duration>=@numframes*0.5 - @ballsprite.y += @addyball - @ballsprite.angle -= @addangle - @ballsprite.zoom_x += @addzoomball - @ballsprite.zoom_y += @addzoomball + 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 - @blacksprites[1].y += @addy - @blacksprites[0].y = @blacksprites[1].y - @bgsprite.zoom_x += @addzoom - @bgsprite.zoom_y += @addzoom + # 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 - @duration -= 1 end end #============================================================================= # HGSS trainer water day #============================================================================= - class WavyThreeBallUp - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return + 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") + @buffer = Graphics.snap_to_bitmap + dispose if !@black_bitmap || !@ball_bitmap || !@buffer + end + + def initialize_sprites + # Black background + @black_bg_sprite = new_sprite(0, 0, @black_bitmap) + @black_bg_sprite.z = 1 + @black_bg_sprite.zoom_y = 2.0 + # Overworld strips (they go all wavy) + rect = Rect.new(0, 0, Graphics.width, 4) + for i in 0...Graphics.height / 4 + @sprites[i] = new_sprite(0, i * 4, @buffer) + @sprites[i].z = 2 + rect.y = i * 4 + @sprites[i].src_rect = rect end - @blackbitmap = RPG::Cache.transition("black_half") - @ballbitmap = RPG::Cache.transition("ball_small") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @rearsprite = Sprite.new(@viewport) - @rearsprite.z = 1 - @rearsprite.zoom_y = 2.0 - @rearsprite.bitmap = @blackbitmap - @bgsprites = [] - rect = Rect.new(0,0,@width,2) - for i in 0...@height/2 - @bgsprites[i] = Sprite.new(@viewport) - @bgsprites[i].y = i*2 - @bgsprites[i].z = 2 - @bgsprites[i].bitmap = @buffer - rect.y = i*2 - @bgsprites[i].src_rect = rect - end - @blacksprites = [] - @ballsprites = [] + # Ball sprites + @ball_sprites = [] for i in 0...3 - @blacksprites[i] = Sprite.new(@viewport) - @blacksprites[i].x = (i-1)*@width*2/3 - @blacksprites[i].y = [@height*1.5,@height*3.25,@height*2.5][i] - @blacksprites[i].z = 3 - @blacksprites[i].zoom_y = 2.0 - @blacksprites[i].bitmap = @blackbitmap - @ballsprites[i] = Sprite.new(@viewport) - @ballsprites[i].x = (2*i+1)*@width/6 - @ballsprites[i].y = [@height*1.5,@height*3.25,@height*2.5][i] - @ballsprites[i].z = 4 - @ballsprites[i].ox = @ballbitmap.width/2 - @ballsprites[i].oy = @ballbitmap.height/2 - @ballsprites[i].bitmap = @ballbitmap + @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 = [] + for i in 0...3 + @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 - @suby = (@height*3.5)/(@numframes*0.6) - @angmult = 4/(@numframes/50.0) end - def disposed?; @disposed; end + def set_up_timings + @ball_rising_start = @duration * 0.4 + end - def dispose - return if disposed? + def dispose_all + # Dispose sprites + @black_bg_sprite.dispose if @black_bg_sprite + @ball_sprites.each { |s| s.dispose if s } + @ball_sprites.clear + @black_trail_sprites.each { |s| s.dispose if s } + @black_trail_sprites.clear + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - @rearsprite.dispose if @rearsprite - for i in @bgsprites; i.dispose if i; end - @bgsprites.clear - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - for i in @ballsprites; i.dispose if i; end - @ballsprites.clear - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - angadd = (@numframes-@duration)*@angmult - amp = 24*angadd/16; amp = 24 if amp>24 - for i in 0...@bgsprites.length - @bgsprites[i].x = amp*Math.sin((i+angadd)*Math::PI/48)*((i%2)*2-1) - end - if @duration<@numframes*0.6 - for i in 0...3 - @blacksprites[i].y -= @suby - @blacksprites[i].y = 0 if @blacksprites[i].y<0 - @ballsprites[i].y -= @suby - @ballsprites[i].angle += (2*(i%2)-1)*(360.0/(0.2*@numframes)) - 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 - @duration -= 1 end end #============================================================================= # HGSS trainer water night #============================================================================= - class WavySpinBall - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @blackbitmap = RPG::Cache.transition("black_half") - @ballbitmap = RPG::Cache.transition("ball_large") - @buffer = Graphics.snap_to_bitmap - if !@blackbitmap || !@ballbitmap || !@buffer - @disposed = true - return - end - @width = @buffer.width - @height = @buffer.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @rearsprite = Sprite.new(@viewport) - @rearsprite.z = 1 - @rearsprite.zoom_y = 2.0 - @rearsprite.bitmap = @blackbitmap - @bgsprites = [] - rect = Rect.new(0,0,@width,2) - for i in 0...@height/2 - @bgsprites[i] = Sprite.new(@viewport) - @bgsprites[i].y = i*2 - @bgsprites[i].z = 2 - @bgsprites[i].bitmap = @buffer - rect.y = i*2 - @bgsprites[i].src_rect = rect - end - @ballsprite = Sprite.new(@viewport) - @ballsprite.x = @width/2 - @ballsprite.y = @height/2 - @ballsprite.z = 3 - @ballsprite.ox = @ballbitmap.width/2 - @ballsprite.oy = @ballbitmap.height/2 - @ballsprite.visible = false - @ballsprite.bitmap = @ballbitmap - @blacksprite = Sprite.new(@viewport) - @blacksprite.x = @width/2 - @blacksprite.y = @height/2 - @blacksprite.z = 4 - @blacksprite.ox = @blackbitmap.width/2 - @blacksprite.oy = @blackbitmap.height/2 - @blacksprite.visible = false - @blacksprite.bitmap = @blackbitmap - @angmult = 4/(@numframes/50.0) + 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") + @buffer = Graphics.snap_to_bitmap + dispose if !@black_bitmap || !@ball_bitmap || !@buffer end - def disposed?; @disposed; end + def initialize_sprites + # Black background + @black_bg_sprite = new_sprite(0, 0, @black_bitmap) + @black_bg_sprite.z = 1 + @black_bg_sprite.zoom_y = 2.0 + # Overworld strips (they go all wavy) + rect = Rect.new(0, 0, Graphics.width, 4) + for i in 0...Graphics.height / 4 + @sprites[i] = new_sprite(0, i * 4, @buffer) + @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 dispose - return if disposed? + def set_up_timings + @ball_appear_end = @duration * 0.4 + @black_appear_start = @duration * 0.5 + end + + def dispose_all + # Dispose sprites + @black_bg_sprite.dispose if @black_bg_sprite + @ball_sprite.dispose if @ball_sprite + @black_sprite.dispose if @black_sprite + # Dispose bitmaps + @black_bitmap.dispose if @black_bitmap + @ball_bitmap.dispose if @ball_bitmap @buffer.dispose if @buffer - @buffer = nil - @blackbitmap.dispose if @blackbitmap - @blackbitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - @rearsprite.dispose if @rearsprite - for i in @bgsprites; i.dispose if i; end - @bgsprites.clear - @ballsprite.dispose if @ballsprite - @blacksprite.dispose if @blacksprite - @viewport.dispose if @viewport - @disposed = true end - def update - return if disposed? - if @duration==0 - dispose - else - angadd = (@numframes-@duration)*@angmult - amp = 24*angadd/16; amp = 24 if amp>24 - for i in 0...@bgsprites.length - @bgsprites[i].x = amp*Math.sin((i+angadd)*Math::PI/48)*((i%2)*2-1) - end - @ballsprite.visible = true - if @duration>=@numframes*0.6 - @ballsprite.opacity = 255*(@numframes-@duration)/(@numframes*0.4) - @ballsprite.angle = -360.0*(@numframes-@duration)/(@numframes*0.4) - elsif @duration<@numframes*0.5 - @blacksprite.visible = true - @blacksprite.zoom_x = (@numframes*0.5-@duration)/(@numframes*0.5) - @blacksprite.zoom_y = 2*(@numframes*0.5-@duration)/(@numframes*0.5) - 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 - @duration -= 1 end end #============================================================================= # HGSS double trainers #============================================================================= - class FourBallBurst - def initialize(numframes) - @numframes = numframes - @duration = numframes - @disposed = false - if @numframes<=0 - @disposed = true - return - end - @black1bitmap = RPG::Cache.transition("black_wedge_1") - @black2bitmap = RPG::Cache.transition("black_wedge_2") - @black3bitmap = RPG::Cache.transition("black_wedge_3") - @black4bitmap = RPG::Cache.transition("black_wedge_4") - @ballbitmap = RPG::Cache.transition("ball_small") - if !@black1bitmap || !@black2bitmap || !@black3bitmap || !@black4bitmap || !@ballbitmap - @disposed = true - return - end - @width = Graphics.width - @height = Graphics.height - @viewport = Viewport.new(0,0,@width,@height) - @viewport.z = 99999 - @ballsprites = [] - for i in 0...4 - @ballsprites[i] = Sprite.new(@viewport) - @ballsprites[i].x = @width/2 - @ballsprites[i].y = @height/2 - @ballsprites[i].z = [2,1,3,0][i] - @ballsprites[i].ox = @ballbitmap.width/2 - @ballsprites[i].oy = @ballbitmap.height/2 - @ballsprites[i].bitmap = @ballbitmap - end - @blacksprites = [] - for i in 0...4 - b = [@black1bitmap,@black2bitmap,@black3bitmap,@black4bitmap][i] - @blacksprites[i] = Sprite.new(@viewport) - @blacksprites[i].x = (i==1) ? 0 : @width/2 - @blacksprites[i].y = (i==2) ? 0 : @height/2 - @blacksprites[i].ox = (i%2==0) ? b.width/2 : 0 - @blacksprites[i].oy = (i%2==0) ? 0 : b.height/2 - @blacksprites[i].zoom_x = (i%2==0) ? 0.0 : 1.0 - @blacksprites[i].zoom_y = (i%2==0) ? 1.0 : 0.0 - @blacksprites[i].visible = false - @blacksprites[i].bitmap = b - end - @addxball = (@width/2+@ballbitmap.width/2)/(@numframes*0.4) - @addyball = (@height/2+@ballbitmap.height/2)/(@numframes*0.4) - @addzoom = 1.0/(@numframes*0.6) + 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 disposed?; @disposed; end - - def dispose - return if disposed? - @black1bitmap.dispose if @black1bitmap - @black1bitmap = nil - @black2bitmap.dispose if @black2bitmap - @black2bitmap = nil - @black3bitmap.dispose if @black3bitmap - @black3bitmap = nil - @black4bitmap.dispose if @black4bitmap - @black4bitmap = nil - @ballbitmap.dispose if @ballbitmap - @ballbitmap = nil - for i in @ballsprites; i.dispose if i; end - @ballsprites.clear - for i in @blacksprites; i.dispose if i; end - @blacksprites.clear - @viewport.dispose if @viewport - @disposed = true + def initialize_sprites + # Ball sprites + @ball_sprites = [] + for i in 0...4 + @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 + for i in 0...4 + 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 % 2 == 0) ? b.width / 2 : 0, (i % 2 == 0) ? 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 update - return if disposed? - if @duration==0 - dispose - elsif @duration>=@numframes*0.6 - for i in 0...@ballsprites.length - @ballsprites[i].x += (i==1) ? @addxball : (i==3) ? -@addxball : 0 - @ballsprites[i].y += (i==0) ? @addyball : (i==2) ? -@addyball : 0 + def set_up_timings + @ball_appear_end = @duration * 0.4 + end + + def dispose_all + # Dispose sprites + @ball_sprites.each { |s| s.dispose if s } + @ball_sprites.clear + # Dispose bitmaps + @black_1_bitmap.dispose if @black_1_bitmap + @black_2_bitmap.dispose if @black_2_bitmap + @black_3_bitmap.dispose if @black_3_bitmap + @black_4_bitmap.dispose if @black_4_bitmap + @ball_bitmap.dispose if @ball_bitmap + 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 - for i in 0...@blacksprites.length - @blacksprites[i].visible = true - @blacksprites[i].zoom_x += (i%2==0) ? @addzoom : 0 - @blacksprites[i].zoom_y += (i%2==0) ? 0 : @addzoom + # 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 - @duration -= 1 end end end diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/002_Overworld_BattleIntroAnim.rb b/Data/Scripts/012_Overworld/002_Battle triggering/002_Overworld_BattleIntroAnim.rb index f56cf002e..83bfd466f 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/002_Overworld_BattleIntroAnim.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/002_Overworld_BattleIntroAnim.rb @@ -88,7 +88,8 @@ def pbBattleAnimation(bgm=nil,battletype=0,foe=nil) end # Play main animation Graphics.freeze - Graphics.transition(Graphics.frame_rate*1.25,sprintf("Graphics/Transitions/%s",anim)) + anim = "battle4" + Graphics.transition(25, sprintf("Graphics/Transitions/%s", anim)) viewport.color = Color.new(0,0,0,255) # Ensure screen is black # Slight pause after animation before starting up the battle scene (Graphics.frame_rate/10).times do diff --git a/Data/Scripts/016_UI/001_Non-interactive UI/002_UI_Controls.rb b/Data/Scripts/016_UI/001_Non-interactive UI/002_UI_Controls.rb index dd8173607..4eba2a310 100644 --- a/Data/Scripts/016_UI/001_Non-interactive UI/002_UI_Controls.rb +++ b/Data/Scripts/016_UI/001_Non-interactive UI/002_UI_Controls.rb @@ -35,7 +35,7 @@ class ButtonEventScene < EventScene addLabelForScreen(4, 134, 196, 352, _INTL("Press to open the Ready Menu, where registered items and available field moves can be used. (Default: D)")) set_up_screen(@current_screen) - Graphics.transition(20) + Graphics.transition # Go to next screen when user presses USE onCTrigger.set(method(:pbOnScreenEnd)) end @@ -67,7 +67,7 @@ class ButtonEventScene < EventScene if @current_screen >= last_screen # End scene Graphics.freeze - Graphics.transition(20, "fadetoblack") + Graphics.transition(8, "fadetoblack") scene.dispose else # Next screen diff --git a/Data/Scripts/016_UI/001_Non-interactive UI/007_UI_Credits.rb b/Data/Scripts/016_UI/001_Non-interactive UI/007_UI_Credits.rb index ca7e7e47a..34b2b7b6d 100644 --- a/Data/Scripts/016_UI/001_Non-interactive UI/007_UI_Credits.rb +++ b/Data/Scripts/016_UI/001_Non-interactive UI/007_UI_Credits.rb @@ -76,7 +76,7 @@ IceGod64SoundSpawn Jacob O. Wobbrockthe__end KitsuneKoutaVenom12 Lisa AnthonyWachunga -Luka S.J. +Luka S.J. and everyone else who helped out "mkxp-z" by: @@ -189,7 +189,7 @@ _END_ pbSEStop pbBGMFade(2.0) pbBGMPlay(BGM) - Graphics.transition(20) + Graphics.transition loop do Graphics.update Input.update @@ -198,7 +198,7 @@ _END_ end pbBGMFade(2.0) Graphics.freeze - Graphics.transition(20, "fadetoblack") + Graphics.transition(8, "fadetoblack") @background_sprite.dispose @credit_sprites.each { |s| s.dispose if s } text_viewport.dispose diff --git a/Data/Scripts/019_Utilities/001_Utilities.rb b/Data/Scripts/019_Utilities/001_Utilities.rb index 2e719d0d9..20bf41a79 100644 --- a/Data/Scripts/019_Utilities/001_Utilities.rb +++ b/Data/Scripts/019_Utilities/001_Utilities.rb @@ -567,17 +567,17 @@ def pbLoadRpgxpScene(scene) Graphics.freeze oldscene.disposeSpritesets visibleObjects = pbHideVisibleObjects - Graphics.transition(20) + Graphics.transition Graphics.freeze while $scene && !$scene.is_a?(Scene_Map) $scene.main end - Graphics.transition(20) + Graphics.transition Graphics.freeze $scene = oldscene $scene.createSpritesets pbShowObjects(visibleObjects) - Graphics.transition(20) + Graphics.transition end def pbChooseLanguage diff --git a/Data/Scripts/999_Main/999_Main.rb b/Data/Scripts/999_Main/999_Main.rb index 257b0cbf1..96ccc26fc 100644 --- a/Data/Scripts/999_Main/999_Main.rb +++ b/Data/Scripts/999_Main/999_Main.rb @@ -33,7 +33,7 @@ def mainFunctionDebug Graphics.freeze $scene = pbCallTitle $scene.main until $scene.nil? - Graphics.transition(20) + Graphics.transition rescue Hangup pbPrintException($!) if !$DEBUG pbEmergencySave