More FPS agnosticism, fixed pause after finishing an event's repeating move route

This commit is contained in:
Maruno17
2023-05-24 21:20:20 +01:00
parent 167155c67d
commit c756e2647a
30 changed files with 947 additions and 847 deletions

View File

@@ -98,8 +98,6 @@ class Battle::Scene
# Update other graphics
@sprites["battle_bg"].update if @sprites["battle_bg"].respond_to?("update")
Graphics.update
@frameCounter += 1
@frameCounter = @frameCounter % (Graphics.frame_rate * 12 / 20)
end
def pbInputUpdate
@@ -114,9 +112,9 @@ class Battle::Scene
cw&.update
@battle.battlers.each_with_index do |b, i|
next if !b
@sprites["dataBox_#{i}"]&.update(@frameCounter)
@sprites["pokemon_#{i}"]&.update(@frameCounter)
@sprites["shadow_#{i}"]&.update(@frameCounter)
@sprites["dataBox_#{i}"]&.update
@sprites["pokemon_#{i}"]&.update
@sprites["shadow_#{i}"]&.update
end
end

View File

@@ -3,12 +3,11 @@ class Battle::Scene
# Create the battle scene and its elements
#=============================================================================
def initialize
@battle = nil
@abortable = false
@aborted = false
@battleEnd = false
@animations = []
@frameCounter = 0
@battle = nil
@abortable = false
@aborted = false
@battleEnd = false
@animations = []
end
# Called whenever the battle begins.

View File

@@ -225,8 +225,8 @@ class Battle::Scene
elsif battler.hp < oldHP
pbCommonAnimation("HealthDown", battler) if showAnim && @battle.showAnims
end
@sprites["dataBox_#{battler.index}"].animateHP(oldHP, battler.hp, battler.totalhp)
while @sprites["dataBox_#{battler.index}"].animatingHP
@sprites["dataBox_#{battler.index}"].animate_hp(oldHP, battler.hp)
while @sprites["dataBox_#{battler.index}"].animating_hp?
pbUpdate
end
end
@@ -253,7 +253,7 @@ class Battle::Scene
targets.each do |t|
anim = Animation::BattlerDamage.new(@sprites, @viewport, t[0].index, t[2])
damageAnims.push(anim)
@sprites["dataBox_#{t[0].index}"].animateHP(t[1], t[0].hp, t[0].totalhp)
@sprites["dataBox_#{t[0].index}"].animate_hp(t[1], t[0].hp)
end
# Update loop
loop do
@@ -261,7 +261,7 @@ class Battle::Scene
pbUpdate
allDone = true
targets.each do |t|
next if !@sprites["dataBox_#{t[0].index}"].animatingHP
next if !@sprites["dataBox_#{t[0].index}"].animating_hp?
allDone = false
break
end
@@ -286,8 +286,8 @@ class Battle::Scene
endExpLevel = tempExp2 - startExp
expRange = endExp - startExp
dataBox = @sprites["dataBox_#{battler.index}"]
dataBox.animateExp(startExpLevel, endExpLevel, expRange)
while dataBox.animatingExp
dataBox.animate_exp(startExpLevel, endExpLevel, expRange)
while dataBox.animating_exp?
pbUpdate
end
end

View File

@@ -4,14 +4,20 @@
class Battle::Scene::PokemonDataBox < Sprite
attr_reader :battler
attr_accessor :selected
attr_reader :animatingHP
attr_reader :animatingExp
# Time in seconds to fully fill the Exp bar (from empty).
EXP_BAR_FILL_TIME = 1.75
# Time in seconds for this data box to flash when the Exp fully fills.
EXP_FULL_FLASH_DURATION = 0.2
# Maximum time in seconds to make a change to the HP bar.
HP_BAR_CHANGE_TIME = 1.0
# Time (in seconds) for one complete sprite bob cycle (up and down) while
# choosing a command for this battler or when this battler is being chosen as
# a target. Set to nil to prevent bobbing.
BOBBING_DURATION = 0.6
# Height in pixels of a status icon
STATUS_ICON_HEIGHT = 16
# Text colors
NAME_BASE_COLOR = Color.new(72, 72, 72)
NAME_SHADOW_COLOR = Color.new(184, 184, 184)
MALE_BASE_COLOR = Color.new(48, 96, 216)
@@ -21,18 +27,14 @@ class Battle::Scene::PokemonDataBox < Sprite
def initialize(battler, sideSize, viewport = nil)
super(viewport)
@battler = battler
@sprites = {}
@spriteX = 0
@spriteY = 0
@spriteBaseX = 0
@selected = 0
@frame = 0
@showHP = false # Specifically, show the HP numbers
@animatingHP = false
@showExp = false # Specifically, show the Exp bar
@animatingExp = false
@expFlash = 0
@battler = battler
@sprites = {}
@spriteX = 0
@spriteY = 0
@spriteBaseX = 0
@selected = 0
@show_hp_numbers = false
@show_exp_bar = false
initializeDataBoxGraphic(sideSize)
initializeOtherGraphics(viewport)
refresh
@@ -45,8 +47,8 @@ class Battle::Scene::PokemonDataBox < Sprite
bgFilename = ["Graphics/UI/Battle/databox_normal",
"Graphics/UI/Battle/databox_normal_foe"][@battler.index % 2]
if onPlayerSide
@showHP = true
@showExp = true
@show_hp_numbers = true
@show_exp_bar = true
end
else # Multiple Pokémon on side, use the thin dara box BG
bgFilename = ["Graphics/UI/Battle/databox_thin",
@@ -143,7 +145,7 @@ class Battle::Scene::PokemonDataBox < Sprite
@sprites.each do |i|
i[1].visible = value if !i[1].disposed?
end
@expBar.visible = (value && @showExp)
@expBar.visible = (value && @show_exp_bar)
end
def color=(value)
@@ -159,38 +161,46 @@ class Battle::Scene::PokemonDataBox < Sprite
end
def hp
return (@animatingHP) ? @currentHP : @battler.hp
return (animating_hp?) ? @anim_hp_current : @battler.hp
end
def exp_fraction
return 0.0 if @rangeExp == 0
return (@animatingExp) ? @currentExp.to_f / @rangeExp : @battler.pokemon.exp_fraction
if animating_exp?
return 0.0 if @anim_exp_range == 0
return @anim_exp_current.to_f / @anim_exp_range
end
return @battler.pokemon.exp_fraction
end
def animateHP(oldHP, newHP, rangeHP)
@currentHP = oldHP
@endHP = newHP
@rangeHP = rangeHP
# NOTE: A change in HP takes the same amount of time to animate, no matter
# how big a change it is.
@hpIncPerFrame = (newHP - oldHP).abs / (HP_BAR_CHANGE_TIME * Graphics.frame_rate)
# minInc is the smallest amount that HP is allowed to change per frame.
# This avoids a tiny change in HP still taking HP_BAR_CHANGE_TIME seconds.
minInc = (rangeHP * 4) / (@hpBarBitmap.width * HP_BAR_CHANGE_TIME * Graphics.frame_rate)
@hpIncPerFrame = minInc if @hpIncPerFrame < minInc
@animatingHP = true
# NOTE: A change in HP takes the same amount of time to animate, no matter how
# big a change it is.
def animate_hp(old_val, new_val)
return if old_val == new_val
@anim_hp_start = old_val
@anim_hp_end = new_val
@anim_hp_current = old_val
@anim_hp_timer_start = System.uptime
end
def animateExp(oldExp, newExp, rangeExp)
return if rangeExp == 0
@currentExp = oldExp
@endExp = newExp
@rangeExp = rangeExp
# NOTE: Filling the Exp bar from empty to full takes EXP_BAR_FILL_TIME
# seconds no matter what. Filling half of it takes half as long, etc.
@expIncPerFrame = rangeExp / (EXP_BAR_FILL_TIME * Graphics.frame_rate)
@animatingExp = true
pbSEPlay("Pkmn exp gain") if @showExp
def animating_hp?
return @anim_hp_timer_start != nil
end
# NOTE: Filling the Exp bar from empty to full takes EXP_BAR_FILL_TIME seconds
# no matter what. Filling half of it takes half as long, etc.
def animate_exp(old_val, new_val, range)
return if old_val == new_val || range == 0 || !@show_exp_bar
@anim_exp_start = old_val
@anim_exp_end = new_val
@anim_exp_range = range
@anim_exp_duration_mult = (new_val - old_val).abs / range.to_f
@anim_exp_current = old_val
@anim_exp_timer_start = System.uptime
pbSEPlay("Pkmn exp gain") if @show_exp_bar
end
def animating_exp?
return @anim_exp_timer_start != nil
end
def pbDrawNumber(number, btmp, startX, startY, align = 0)
@@ -284,15 +294,15 @@ class Battle::Scene::PokemonDataBox < Sprite
draw_shiny_icon
draw_special_form_icon
draw_owned_icon
refreshHP
refreshExp
refresh_hp
refresh_exp
end
def refreshHP
def refresh_hp
@hpNumbers.bitmap.clear
return if !@battler.pokemon
# Show HP numbers
if @showHP
if @show_hp_numbers
pbDrawNumber(self.hp, @hpNumbers.bitmap, 54, 2, 1)
pbDrawNumber(-1, @hpNumbers.bitmap, 54, 2) # / char
pbDrawNumber(@battler.totalhp, @hpNumbers.bitmap, 70, 2)
@@ -307,14 +317,14 @@ class Battle::Scene::PokemonDataBox < Sprite
w = ((w / 2.0).round) * 2
end
@hpBar.src_rect.width = w
hpColor = 0 # Green bar
hpColor = 0 # Green bar
hpColor = 1 if self.hp <= @battler.totalhp / 2 # Yellow bar
hpColor = 2 if self.hp <= @battler.totalhp / 4 # Red bar
@hpBar.src_rect.y = hpColor * @hpBarBitmap.height / 3
end
def refreshExp
return if !@showExp
def refresh_exp
return if !@show_exp_bar
w = exp_fraction * @expBarBitmap.width
# NOTE: The line below snaps the bar's width to the nearest 2 pixels, to
# fit in with the rest of the graphics which are doubled in size.
@@ -322,80 +332,82 @@ class Battle::Scene::PokemonDataBox < Sprite
@expBar.src_rect.width = w
end
def updateHPAnimation
return if !@animatingHP
if @currentHP < @endHP # Gaining HP
@currentHP += @hpIncPerFrame
@currentHP = @endHP if @currentHP >= @endHP
elsif @currentHP > @endHP # Losing HP
@currentHP -= @hpIncPerFrame
@currentHP = @endHP if @currentHP <= @endHP
end
def update_hp_animation
return if !animating_hp?
@anim_hp_current = lerp(@anim_hp_start, @anim_hp_end, HP_BAR_CHANGE_TIME,
@anim_hp_timer_start, System.uptime)
# Refresh the HP bar/numbers
refreshHP
@animatingHP = false if @currentHP == @endHP
refresh_hp
# End the HP bar filling animation
if @anim_hp_current == @anim_hp_end
@anim_hp_start = nil
@anim_hp_end = nil
@anim_hp_timer_start = nil
@anim_hp_current = nil
end
end
def updateExpAnimation
return if !@animatingExp
if !@showExp # Not showing the Exp bar, no need to waste time animating it
@currentExp = @endExp
@animatingExp = false
def update_exp_animation
return if !animating_exp?
if !@show_exp_bar # Not showing the Exp bar, no need to waste time animating it
@anim_exp_timer_start = nil
return
end
if @currentExp < @endExp # Gaining Exp
@currentExp += @expIncPerFrame
@currentExp = @endExp if @currentExp >= @endExp
elsif @currentExp > @endExp # Losing Exp
@currentExp -= @expIncPerFrame
@currentExp = @endExp if @currentExp <= @endExp
end
duration = EXP_BAR_FILL_TIME * @anim_exp_duration_mult
@anim_exp_current = lerp(@anim_exp_start, @anim_exp_end, duration,
@anim_exp_timer_start, System.uptime)
# Refresh the Exp bar
refreshExp
return if @currentExp != @endExp # Exp bar still has more to animate
# Exp bar is completely filled, level up with a flash and sound effect
if @currentExp >= @rangeExp
if @expFlash == 0
pbSEStop
@expFlash = Graphics.frame_rate / 5
pbSEPlay("Pkmn exp full")
self.flash(Color.new(64, 200, 248, 192), @expFlash)
@sprites.each do |i|
i[1].flash(Color.new(64, 200, 248, 192), @expFlash) if !i[1].disposed?
end
refresh_exp
return if @anim_exp_current != @anim_exp_end # Exp bar still has more to animate
# End the Exp bar filling animation
if @anim_exp_current >= @anim_exp_range
if @anim_exp_flash_timer_start
# Waiting for Exp full flash to finish
return if System.uptime - @anim_exp_flash_timer_start < EXP_FULL_FLASH_DURATION
else
@expFlash -= 1
@animatingExp = false if @expFlash == 0
# Show the Exp full flash
@anim_exp_flash_timer_start = System.uptime
pbSEStop
pbSEPlay("Pkmn exp full")
flash_duration = EXP_FULL_FLASH_DURATION * Graphics.frame_rate # Must be in frames, not seconds
self.flash(Color.new(64, 200, 248, 192), flash_duration)
@sprites.each do |i|
i[1].flash(Color.new(64, 200, 248, 192), flash_duration) if !i[1].disposed?
end
return
end
else
pbSEStop
# Exp bar has finished filling, end animation
@animatingExp = false
end
pbSEStop if !@anim_exp_flash_timer_start
@anim_exp_start = nil
@anim_exp_end = nil
@anim_exp_duration_mult = nil
@anim_exp_current = nil
@anim_exp_timer_start = nil
@anim_exp_flash_timer_start = nil
end
QUARTER_ANIM_PERIOD = Graphics.frame_rate * 3 / 20
def updatePositions(frameCounter)
def update_positions
self.x = @spriteX
self.y = @spriteY
# Data box bobbing while Pokémon is selected
if @selected == 1 || @selected == 2 # Choosing commands/targeted or damaged
case (frameCounter / QUARTER_ANIM_PERIOD).floor
if (@selected == 1 || @selected == 2) && BOBBING_DURATION # Choosing commands/targeted
bob_delta = System.uptime % BOBBING_DURATION # 0-BOBBING_DURATION
bob_frame = (4 * bob_delta / BOBBING_DURATION).floor
case bob_frame
when 1 then self.y = @spriteY - 2
when 3 then self.y = @spriteY + 2
end
end
end
def update(frameCounter = 0)
super()
def update
super
# Animate HP bar
updateHPAnimation
update_hp_animation
# Animate Exp bar
updateExpAnimation
update_exp_animation
# Update coordinates of the data box
updatePositions(frameCounter)
update_positions
pbUpdateSpriteHash(@sprites)
end
end
@@ -502,6 +514,13 @@ class Battle::Scene::BattlerSprite < RPG::Sprite
attr_accessor :selected
attr_reader :sideSize
# Time (in seconds) for one complete sprite bob cycle (up and down) while
# choosing a command for this battler. Set to nil to prevent bobbing.
COMMAND_BOBBING_DURATION = 0.6
# Time (in seconds) for one complete blinking cycle while this battler is
# being chosen as a target. Set to nil to prevent blinking.
TARGET_BLINKING_DURATION = 0.3
def initialize(viewport, sideSize, index, battleAnimations)
super(viewport)
@pkmn = nil
@@ -511,7 +530,6 @@ class Battle::Scene::BattlerSprite < RPG::Sprite
# @selected: 0 = not selected, 1 = choosing action bobbing for this Pokémon,
# 2 = flashing when targeted
@selected = 0
@frame = 0
@updating = false
@spriteX = 0 # Actual x coordinate
@spriteY = 0 # Actual y coordinate
@@ -588,10 +606,7 @@ class Battle::Scene::BattlerSprite < RPG::Sprite
@pkmn&.play_cry
end
QUARTER_ANIM_PERIOD = Graphics.frame_rate * 3 / 20
SIXTH_ANIM_PERIOD = Graphics.frame_rate * 2 / 20
def update(frameCounter = 0)
def update
return if !@_iconBitmap
@updating = true
# Update bitmap
@@ -599,8 +614,10 @@ class Battle::Scene::BattlerSprite < RPG::Sprite
self.bitmap = @_iconBitmap.bitmap
# Pokémon sprite bobbing while Pokémon is selected
@spriteYExtra = 0
if @selected == 1 # When choosing commands for this Pokémon
case (frameCounter / QUARTER_ANIM_PERIOD).floor
if @selected == 1 && COMMAND_BOBBING_DURATION # When choosing commands for this Pokémon
bob_delta = System.uptime % COMMAND_BOBBING_DURATION # 0-COMMAND_BOBBING_DURATION
bob_frame = (4 * bob_delta / COMMAND_BOBBING_DURATION).floor
case bob_frame
when 1 then @spriteYExtra = 2
when 3 then @spriteYExtra = -2
end
@@ -609,11 +626,10 @@ class Battle::Scene::BattlerSprite < RPG::Sprite
self.y = self.y
self.visible = @spriteVisible
# Pokémon sprite blinking when targeted
if @selected == 2 && @spriteVisible
case (frameCounter / SIXTH_ANIM_PERIOD).floor
when 2, 5 then self.visible = false
else self.visible = true
end
if @selected == 2 && @spriteVisible && TARGET_BLINKING_DURATION
blink_delta = System.uptime % TARGET_BLINKING_DURATION # 0-TARGET_BLINKING_DURATION
blink_frame = (3 * blink_delta / TARGET_BLINKING_DURATION).floor
self.visible = (blink_frame != 0)
end
@updating = false
end
@@ -673,7 +689,7 @@ class Battle::Scene::BattlerShadowSprite < RPG::Sprite
pbSetPosition
end
def update(frameCounter = 0)
def update
return if !@_iconBitmap
# Update bitmap
@_iconBitmap.update