mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 09:10:49 +02:00
fixed full screen flashing in battles
This commit is contained in:
@@ -20,6 +20,15 @@
|
|||||||
Leaving it deliberately undoes nothing -- reverting would discard whatever
|
Leaving it deliberately undoes nothing -- reverting would discard whatever
|
||||||
had been changed since.
|
had been changed since.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **The hit flash whited out the whole screen.** The engine draws it as a
|
||||||
|
full-screen white rectangle, which is a flash on a white battle field and
|
||||||
|
a whiteout of the map, the HUD and the text box over a world. It is now
|
||||||
|
dropped on the way past and put back where it was ever about: the two
|
||||||
|
Pokemon go solid white for those frames, silhouette and all, and nothing
|
||||||
|
else in the frame moves.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Hotkey `3` walks the angle rungs only and steps over `FULL`.** The key is
|
- **Hotkey `3` walks the angle rungs only and steps over `FULL`.** The key is
|
||||||
|
|||||||
@@ -278,6 +278,11 @@ end
|
|||||||
-- yet (the terrain mesh is still building, the driver has no depth support).
|
-- yet (the terrain mesh is still building, the driver has no depth support).
|
||||||
-- nil is not a failure: the caller simply leaves the battle screen as the
|
-- nil is not a failure: the caller simply leaves the battle screen as the
|
||||||
-- engine drew it for that frame.
|
-- engine drew it for that frame.
|
||||||
|
-- White, for the hit flash. The shader replaces the card's colour outright
|
||||||
|
-- rather than multiplying it, so this is the sprite's own silhouette turned
|
||||||
|
-- solid white -- not a lightened picture of itself.
|
||||||
|
BattleScene.FLASH_COLOR = { 1, 1, 1 }
|
||||||
|
|
||||||
function BattleScene.render(state, arena, textures, token)
|
function BattleScene.render(state, arena, textures, token)
|
||||||
if not (state and state.map and arena) then return nil end
|
if not (state and state.map and arena) then return nil end
|
||||||
if not Voxel3D.available() then return nil end
|
if not Voxel3D.available() then return nil end
|
||||||
@@ -358,10 +363,18 @@ function BattleScene.render(state, arena, textures, token)
|
|||||||
-- front of it, and the alpha discard cuts the sprite's own outline out of
|
-- front of it, and the alpha discard cuts the sprite's own outline out of
|
||||||
-- the card. A small camera-ward pull keeps a card rooted to the ground
|
-- the card. A small camera-ward pull keeps a card rooted to the ground
|
||||||
-- plane from z-fighting the tile it is standing on.
|
-- plane from z-fighting the tile it is standing on.
|
||||||
|
-- The engine's hit flash is a full-screen white rectangle, which on a
|
||||||
|
-- white battle field is a flash and over a world is a whiteout of the
|
||||||
|
-- map, the HUD and the text box alike. It is dropped on the way past
|
||||||
|
-- (see OverworldBattle) and put back HERE, on the two things it was ever
|
||||||
|
-- about: the mons themselves go solid white for those frames.
|
||||||
|
local flashing = textures and textures.flash
|
||||||
|
if flashing then Voxel3D.flatten(BattleScene.FLASH_COLOR) end
|
||||||
for _, card in ipairs(monCards(arena, groundY, textures)) do
|
for _, card in ipairs(monCards(arena, groundY, textures)) do
|
||||||
Voxel3D.draw(BattleBillboard.mesh(), card.tex, card.model,
|
Voxel3D.draw(BattleBillboard.mesh(), card.tex, card.model,
|
||||||
BattleBillboard.PULL)
|
BattleBillboard.PULL)
|
||||||
end
|
end
|
||||||
|
if flashing then Voxel3D.flatten(nil) end
|
||||||
-- grass and flowers ride the same camera-ward pull the free-roam pass
|
-- grass and flowers ride the same camera-ward pull the free-roam pass
|
||||||
-- gives them, measured against THIS camera's pitch rather than the
|
-- gives them, measured against THIS camera's pitch rather than the
|
||||||
-- orbit's -- there is no character here for them to overdraw, but the
|
-- orbit's -- there is no character here for them to overdraw, but the
|
||||||
|
|||||||
+28
-5
@@ -340,11 +340,21 @@ local function withoutBackgroundFill(battle, fn)
|
|||||||
if mode == "fill" and x == 0 and y == 0
|
if mode == "fill" and x == 0 and y == 0
|
||||||
and w == BattleScene.GB_W and h == BattleScene.GB_H then
|
and w == BattleScene.GB_W and h == BattleScene.GB_H then
|
||||||
local r, gr, b, a = g.getColor()
|
local r, gr, b, a = g.getColor()
|
||||||
if r > 0.99 and gr > 0.99 and b > 0.99 and a > 0.99 then
|
if r > 0.99 and gr > 0.99 and b > 0.99 then
|
||||||
local target = g.getCanvas()
|
-- Two different full-frame whites, both replaced rather than drawn.
|
||||||
if target ~= nil
|
--
|
||||||
and (target == battle.bgCanvas or target == battle.waveCanvas) then
|
-- OPAQUE is the battle's background, and on the offscreen canvases it
|
||||||
g.clear(0, 0, 0, 0)
|
-- doubles as their clear, so there it becomes a transparent one.
|
||||||
|
--
|
||||||
|
-- TRANSLUCENT is the hit flash. Over a white field that reads as a
|
||||||
|
-- flash; over a world it whites out the map, the HUD and the text box
|
||||||
|
-- together. BattleScene puts it back on the mons alone.
|
||||||
|
if a > 0.99 then
|
||||||
|
local target = g.getCanvas()
|
||||||
|
if target ~= nil
|
||||||
|
and (target == battle.bgCanvas or target == battle.waveCanvas) then
|
||||||
|
g.clear(0, 0, 0, 0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -471,6 +481,18 @@ function OverworldBattle.sideTexture(battle, side)
|
|||||||
return { canvas = canvas, ax = ax, ay = ay, trainer = trainer }
|
return { canvas = canvas, ax = ax, ay = ay, trainer = trainer }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Whether the hit flash is showing this frame.
|
||||||
|
--
|
||||||
|
-- Mirrors BattleState:draw's own test, because the flash is a DRAW-time
|
||||||
|
-- decision there (a counter plus the frame parity that makes it flicker) and
|
||||||
|
-- there is no seam that reports it. Read-only, so the worst a future engine
|
||||||
|
-- change can do is flash on a frame the engine would not have.
|
||||||
|
function OverworldBattle.flashing(battle)
|
||||||
|
local fx = battle and battle.fx
|
||||||
|
if not (fx and fx.flash and fx.flash > 0) then return false end
|
||||||
|
return (battle.frame or 0) % 4 < 2
|
||||||
|
end
|
||||||
|
|
||||||
-- Both sides, or nil when neither has anything to show.
|
-- Both sides, or nil when neither has anything to show.
|
||||||
function OverworldBattle.textures(battle)
|
function OverworldBattle.textures(battle)
|
||||||
if not battle then return nil end
|
if not battle then return nil end
|
||||||
@@ -480,6 +502,7 @@ function OverworldBattle.textures(battle)
|
|||||||
out.enemy = okE and enemy or nil
|
out.enemy = okE and enemy or nil
|
||||||
out.player = okP and player or nil
|
out.player = okP and player or nil
|
||||||
if not (out.enemy or out.player) then return nil end
|
if not (out.enemy or out.player) then return nil end
|
||||||
|
out.flash = OverworldBattle.flashing(battle)
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,24 @@ function Voxel3D.beginGhost()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Flatten whatever is drawn next to one solid colour, or nil to stop.
|
||||||
|
--
|
||||||
|
-- The same `ghost` path the silhouette uses, WITHOUT beginGhost's inverted
|
||||||
|
-- depth test and half alpha -- this is for something drawn normally that
|
||||||
|
-- simply wants to come out one colour, which is what a hit flash on a sprite
|
||||||
|
-- is. beginScene resets the uniform every frame, so a pass that forgets to
|
||||||
|
-- clear it cannot leak into the next one.
|
||||||
|
function Voxel3D.flatten(color)
|
||||||
|
if not (active and activeShader) then return end
|
||||||
|
local sh = activeShader
|
||||||
|
if color then
|
||||||
|
pcall(sh.send, sh, "ghostColor", color)
|
||||||
|
pcall(sh.send, sh, "ghost", 1)
|
||||||
|
else
|
||||||
|
pcall(sh.send, sh, "ghost", 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Voxel3D.endGhost()
|
function Voxel3D.endGhost()
|
||||||
if not active then return end
|
if not active then return end
|
||||||
pcall(love.graphics.setDepthMode, "lequal", true)
|
pcall(love.graphics.setDepthMode, "lequal", true)
|
||||||
|
|||||||
@@ -1374,6 +1374,24 @@ T.check(math.abs(sx - px) < 0.2,
|
|||||||
-- arena floor out from under the two mons pinned to it
|
-- arena floor out from under the two mons pinned to it
|
||||||
T.eq(rig.curve, 0, "the battle camera switches the world curve off")
|
T.eq(rig.curve, 0, "the battle camera switches the world curve off")
|
||||||
|
|
||||||
|
-- ------- the hit flash belongs to the mons, not the screen
|
||||||
|
--
|
||||||
|
-- The engine draws it as a full-screen white rectangle, which is a flash on
|
||||||
|
-- a white battle field and a whiteout of the map, the HUD and the text box
|
||||||
|
-- over a world. It is dropped on the way past and put back on the two cards.
|
||||||
|
local Battles = run.loader.exports.DRAMATIC_SHAPE.lib.require("OverworldBattle")
|
||||||
|
T.eq(Battles.flashing(nil), false, "no battle, no flash")
|
||||||
|
T.eq(Battles.flashing({ fx = {}, frame = 0 }), false,
|
||||||
|
"a battle with no flash counter is not flashing")
|
||||||
|
T.eq(Battles.flashing({ fx = { flash = 0 }, frame = 0 }), false,
|
||||||
|
"nor one whose counter has run out")
|
||||||
|
T.eq(Battles.flashing({ fx = { flash = 16 }, frame = 0 }), true,
|
||||||
|
"a live counter flashes on the frames the engine would")
|
||||||
|
T.eq(Battles.flashing({ fx = { flash = 16 }, frame = 2 }), false,
|
||||||
|
"and is dark on the others, which is what makes it flicker")
|
||||||
|
T.eq(Battles.flashing({ fx = { flash = 16 }, frame = 5 }), true,
|
||||||
|
"on a four-frame cycle")
|
||||||
|
|
||||||
-- ------- the wireframe is forced on in a battle
|
-- ------- the wireframe is forced on in a battle
|
||||||
--
|
--
|
||||||
-- A fight is a staged shot rather than the world being walked through, so it
|
-- A fight is a staged shot rather than the world being walked through, so it
|
||||||
|
|||||||
Reference in New Issue
Block a user