184 lines
3.9 KiB
Go
184 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
rl "github.com/gen2brain/raylib-go/raylib"
|
|
)
|
|
|
|
type TransitionPhase int
|
|
|
|
const (
|
|
TransitionNone TransitionPhase = iota
|
|
TransitionOutFadeScale
|
|
TransitionOutSlide
|
|
TransitionInFadeScale
|
|
)
|
|
|
|
type TransitionDirection int
|
|
|
|
const (
|
|
DirectionForward TransitionDirection = iota
|
|
DirectionBackward
|
|
)
|
|
|
|
type TransitionManager struct {
|
|
active bool
|
|
direction TransitionDirection
|
|
|
|
oldStep int
|
|
newStep int
|
|
|
|
// Single total transition duration (seconds)
|
|
totalSec float32
|
|
|
|
// Sub-phase fractions (must sum to 1.0)
|
|
fadeFrac float32
|
|
slideFrac float32
|
|
inFrac float32
|
|
|
|
// Where we store the linear boundary of the sub-phase in [0..1]
|
|
fadeEnd float32
|
|
slideEnd float32
|
|
|
|
// Accumulated time in seconds
|
|
accumSec float32
|
|
}
|
|
|
|
// NewTransitionManager with one total duration, e.g. 0.5 seconds total
|
|
// Sub-phase fractions: fade=0.3, slide=0.4, fadeIn=0.3 (they sum to 1.0)
|
|
func NewTransitionManager() *TransitionManager {
|
|
return &TransitionManager{
|
|
totalSec: 0.6, // e.g., entire transition 600ms
|
|
fadeFrac: 0.3, // 30% of total time for fade out scale
|
|
slideFrac: 0.4, // 40% of total time for slide
|
|
inFrac: 0.3, // 30% of total time for fade in scale
|
|
}
|
|
}
|
|
|
|
func (t *TransitionManager) Start(oldStep, newStep int) {
|
|
t.active = true
|
|
t.accumSec = 0
|
|
t.oldStep = oldStep
|
|
t.newStep = newStep
|
|
|
|
if newStep > oldStep {
|
|
t.direction = DirectionForward
|
|
} else {
|
|
t.direction = DirectionBackward
|
|
}
|
|
|
|
// Precompute sub-phase boundaries in [0..1]
|
|
t.fadeEnd = t.fadeFrac
|
|
t.slideEnd = t.fadeFrac + t.slideFrac
|
|
// Final inFrac ends at 1.0
|
|
}
|
|
|
|
func (t *TransitionManager) IsActive() bool {
|
|
return t.active
|
|
}
|
|
|
|
// GetPhase returns which phase the transition is currently in.
|
|
func (t *TransitionManager) GetPhase() TransitionPhase {
|
|
if !t.active {
|
|
return TransitionNone
|
|
}
|
|
|
|
// Determine the linear progress
|
|
p := t.accumSec / t.totalSec
|
|
if p < t.fadeEnd {
|
|
return TransitionOutFadeScale
|
|
} else if p < t.slideEnd {
|
|
return TransitionOutSlide
|
|
} else {
|
|
return TransitionInFadeScale
|
|
}
|
|
}
|
|
|
|
// Easing function: "easeInOutCubic" => pronounced slow start, fast middle, slow end
|
|
func easeInOutCubic(p float32) float32 {
|
|
if p < 0.5 {
|
|
return 4 * p * p * p
|
|
}
|
|
f := (2 * p) - 2
|
|
return 0.5*f*f*f + 1
|
|
}
|
|
|
|
// Update returns alpha/scale/offset for old/new steps
|
|
func (t *TransitionManager) Update() (
|
|
oldAlpha, oldScale, oldOffsetX float32,
|
|
newAlpha, newScale, newOffsetX float32,
|
|
) {
|
|
if !t.active {
|
|
return 1, 1, 0, 1, 1, 0
|
|
}
|
|
|
|
// Accumulate variable time
|
|
dt := rl.GetFrameTime() // in seconds
|
|
t.accumSec += dt
|
|
if t.accumSec >= t.totalSec {
|
|
t.active = false
|
|
return 1, 1, 0, 1, 1, 0
|
|
}
|
|
|
|
oldAlpha, oldScale, oldOffsetX = 1, 1, 0
|
|
newAlpha, newScale, newOffsetX = 1, 1, 0
|
|
|
|
slideDir := float32(1)
|
|
if t.direction == DirectionBackward {
|
|
slideDir = -1
|
|
}
|
|
|
|
p := t.accumSec / t.totalSec
|
|
if p > 1 {
|
|
p = 1
|
|
}
|
|
|
|
globalP := easeInOutCubic(p)
|
|
|
|
if p < t.fadeEnd {
|
|
gEnd := easeInOutCubic(t.fadeEnd)
|
|
subE := float32(0)
|
|
if gEnd > 0 {
|
|
subE = globalP / gEnd
|
|
}
|
|
|
|
oldAlpha = 1 - 0.2*subE
|
|
oldScale = 1 - 0.1*subE
|
|
newAlpha = 0
|
|
newScale = 0.9
|
|
newOffsetX = float32(rl.GetScreenWidth()) * slideDir
|
|
|
|
} else if p < t.slideEnd {
|
|
gStart := easeInOutCubic(t.fadeEnd)
|
|
gEnd := easeInOutCubic(t.slideEnd)
|
|
gRange := gEnd - gStart
|
|
subE := float32(0)
|
|
if gRange > 0 {
|
|
subE = (globalP - gStart) / gRange
|
|
}
|
|
|
|
oldAlpha = 0.8
|
|
oldScale = 0.9
|
|
oldOffsetX = -float32(rl.GetScreenWidth()) * subE * slideDir
|
|
newAlpha = 0.8
|
|
newScale = 0.9
|
|
newOffsetX = float32(rl.GetScreenWidth()) * (1 - subE) * slideDir
|
|
|
|
} else {
|
|
gStart := easeInOutCubic(t.slideEnd)
|
|
gEnd := easeInOutCubic(1)
|
|
gRange := gEnd - gStart
|
|
subE := float32(0)
|
|
if gRange > 0 {
|
|
subE = (globalP - gStart) / gRange
|
|
}
|
|
|
|
oldAlpha = 0
|
|
oldScale = 0.9
|
|
oldOffsetX = -float32(rl.GetScreenWidth()) * slideDir
|
|
newAlpha = 0.8 + 0.2*subE
|
|
newScale = 0.9 + 0.1*subE
|
|
newOffsetX = 0
|
|
}
|
|
|
|
return oldAlpha, oldScale, oldOffsetX, newAlpha, newScale, newOffsetX
|
|
}
|