Fix encounter silhouette slide speed and blackout (#577)

The battle intro slide ran at 4px/frame over 40 frames -- twice the
original speed -- and drew the pics in their normal palette instead of
as black silhouettes.

SlidePlayerAndEnemySilhouettesOnScreen scrolls SCX from $90 to 0 at
2px/frame (~72 frames) under the %11100100 silhouette palette, only
running SET_PAL_BATTLE once the pics land. Match that: introSlide starts
at 80 with a 2px/frame offset (80 frames over the full 160px width), and
picImage bakes both pics through PAL_BLACK while introSlide > 0, exactly
like the evolution movie (#279).

parity_battle_intro_chrome waited a hardcoded 45 frames for the slide to
land; bumped to 85 to cover the slower slide.
This commit is contained in:
Bart in 't Veld
2026-08-01 15:25:54 +02:00
parent 22fd196045
commit 88e2ec2042
3 changed files with 22 additions and 11 deletions
+17 -7
View File
@@ -291,10 +291,17 @@ function BattleState:picImage(img)
or PaletteFX.mode == "classic" or PaletteFX.mode == "classic"
if self.grayPics or mono then return grayImage(img) end if self.grayPics or mono then return grayImage(img) end
-- SET_PAL_BATTLE_BLACK covers every battle palette slot, so the pics go -- SET_PAL_BATTLE_BLACK covers every battle palette slot, so the pics go
-- dark with the HP bars while the blackout text is up (#292). Below the -- dark with the HP bars while the blackout text is up (#292). The intro
-- mono check on purpose: the forced-mono modes re-threshold the whole -- silhouette slide (SlidePlayerAndEnemySilhouettesOnScreen) darkens the
-- frame downstream, and the DMG had no SGB darkening to begin with. -- same way: the original slides both pics in under the %11100100
if self.blackedOut then return blackImage(self.data, img) end -- silhouette palette and only runs SET_PAL_BATTLE once they have landed,
-- so a still-sliding pic reads as a black silhouette, exactly like the
-- evolution movie's PAL_BLACK (#577). Below the mono check on purpose:
-- the forced-mono modes re-threshold the whole frame downstream, and the
-- DMG had no SGB darkening to begin with.
if self.blackedOut or (self.introSlide or 0) > 0 then
return blackImage(self.data, img)
end
return fadeImage(img, self:activeBgp()) return fadeImage(img, self:activeBgp())
end end
@@ -1241,8 +1248,11 @@ function BattleState:enter()
-- without a transition (link battles, scripted pushes) -- without a transition (link battles, scripted pushes)
Music.playBattle(self.data, self.musicKind) Music.playBattle(self.data, self.musicKind)
-- intro presentation (SlidePlayerAndEnemySilhouettesOnScreen): both -- intro presentation (SlidePlayerAndEnemySilhouettesOnScreen): both
-- sides slide in; the trainer pics stay up until the send-outs -- sides slide in as black silhouettes. The original scrolls SCX from
self.introSlide = 40 -- $90 to 0 two pixels per frame (72 frames); the port covers the full
-- 160px screen width, so 2px/frame is an 80-frame slide (slide offset is
-- introSlide*2 below). The trainer pics stay up until the send-outs.
self.introSlide = 80
self.showEnemyTrainer = self.kind == "trainer" and self.trainerPic ~= nil self.showEnemyTrainer = self.kind == "trainer" and self.trainerPic ~= nil
-- DrawAllPokeballs (common_text.asm:27) puts the party ball rows AND the -- DrawAllPokeballs (common_text.asm:27) puts the party ball rows AND the
-- HUD corner/underline tiles under them (PlacePlayerHUDTiles / -- HUD corner/underline tiles under them (PlacePlayerHUDTiles /
@@ -5220,7 +5230,7 @@ function BattleState:drawClassic()
if sx == 0 and sy == 0 and fx and fx.shake and fx.shake > 0 then if sx == 0 and sy == 0 and fx and fx.shake and fx.shake > 0 then
sx = self.frame % 4 < 2 and 2 or -2 sx = self.frame % 4 < 2 and 2 or -2
end end
local slide = (self.introSlide or 0) * 4 -- intro slide-in offset local slide = (self.introSlide or 0) * 2 -- intro slide-in offset (2px/frame)
if self:colorMode() then if self:colorMode() then
-- SGB pipeline: gray BG canvas -> (wavy) -> zone recolor with the -- SGB pipeline: gray BG canvas -> (wavy) -> zone recolor with the
+1 -1
View File
@@ -320,7 +320,7 @@ function WideBattle.draw(battle)
if sx == 0 and sy == 0 and fx and fx.shake and fx.shake > 0 then if sx == 0 and sy == 0 and fx and fx.shake and fx.shake > 0 then
sx = battle.frame % 4 < 2 and 2 or -2 sx = battle.frame % 4 < 2 and 2 or -2
end end
local slide = (battle.introSlide or 0) * 4 local slide = (battle.introSlide or 0) * 2
-- Each side keeps its original sprite pixels and placement math: the two -- Each side keeps its original sprite pixels and placement math: the two
-- 160x144 OAM regions are translated apart and clipped into the wider -- 160x144 OAM regions are translated apart and clipped into the wider
+4 -3
View File
@@ -98,8 +98,9 @@ check(wild.queue[1] and wild.queue[1].fn ~= nil,
check(wild.queue[2] and wild.queue[2].text == wild.introText, check(wild.queue[2] and wild.queue[2].text == wild.introText,
"the intro text is still the second queue row") "the intro text is still the second queue row")
-- let the silhouette slide land so the intro box is genuinely up -- let the silhouette slide land so the intro box is genuinely up (the slide
for _ = 1, 45 do wild:update(1 / 60) end -- now runs 80 frames at 2px/frame, matching the original ~2px/frame)
for _ = 1, 85 do wild:update(1 / 60) end
eq(wild.introSlide or 0, 0, "the silhouette slide has landed") eq(wild.introSlide or 0, 0, "the silhouette slide has landed")
eq(wild.introBalls, true, "the window is still open under the intro text") eq(wild.introBalls, true, "the window is still open under the intro text")
eq(currentText(wild), wild.introText, "the intro box is the row on screen") eq(currentText(wild), wild.introText, "the intro box is the row on screen")
@@ -164,7 +165,7 @@ local tr = BattleState.newTrainer(game2, "OPP_YOUNGSTER", 1)
tr.onFinish = function() end tr.onFinish = function() end
tr:enter() tr:enter()
eq(tr.introBalls, true, "the trainer intro opens the same window") eq(tr.introBalls, true, "the trainer intro opens the same window")
for _ = 1, 45 do tr:update(1 / 60) end for _ = 1, 85 do tr:update(1 / 60) end
local ok3, err3, rows3 = snapshotHUD(tr) local ok3, err3, rows3 = snapshotHUD(tr)
check(ok3, "drawHUDs runs during the trainer intro: " .. tostring(err3)) check(ok3, "drawHUDs runs during the trainer intro: " .. tostring(err3))