added variable refresh rate support
This commit is contained in:
parent
84fe6fe9eb
commit
f75618ec44
3 changed files with 113 additions and 67 deletions
|
@ -18,20 +18,23 @@ var topColor = rl.Color{R: 0x20, G: 0x0F, B: 0x3C, A: 0xFF} // #200F3C top
|
||||||
var bottomColor = rl.Color{R: 0x3B, G: 0x0B, B: 0x42, A: 0xFF} // #3B0B42 bottom
|
var bottomColor = rl.Color{R: 0x3B, G: 0x0B, B: 0x42, A: 0xFF} // #3B0B42 bottom
|
||||||
var particleColor = rl.Color{R: 0xD4, G: 0xB0, B: 0xB5, A: 0x80} // D4B0B5 with some transparency
|
var particleColor = rl.Color{R: 0xD4, G: 0xB0, B: 0xB5, A: 0x80} // D4B0B5 with some transparency
|
||||||
|
|
||||||
|
var rng = rand.New(rand.NewSource(time.Now().UnixNano())) // Local RNG
|
||||||
|
|
||||||
func InitBackground(width, height int) {
|
func InitBackground(width, height int) {
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
particles = make([]Particle, 100)
|
particles = make([]Particle, 100)
|
||||||
for i := range particles {
|
for i := range particles {
|
||||||
particles[i].Pos = rl.Vector2{X: float32(rand.Intn(width)), Y: float32(rand.Intn(height))}
|
particles[i].Pos = rl.Vector2{X: float32(rng.Intn(width)), Y: float32(rng.Intn(height))}
|
||||||
particles[i].Vel = rl.Vector2{X: (rand.Float32() - 0.5) * 0.2, Y: (rand.Float32() - 0.5) * 0.2}
|
particles[i].Vel = rl.Vector2{X: (rng.Float32() - 0.5) * 0.2, Y: (rng.Float32() - 0.5) * 0.2}
|
||||||
particles[i].Size = rand.Float32()*1.5 + 0.5 // Particles size ~0.5-2.0
|
particles[i].Size = rng.Float32()*1.5 + 0.5 // Particles size ~0.5-2.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateBackground(screenWidth, screenHeight int) {
|
func UpdateBackground(screenWidth, screenHeight int) {
|
||||||
|
deltaTime := rl.GetFrameTime() // Time in seconds since the last frame
|
||||||
for i := range particles {
|
for i := range particles {
|
||||||
particles[i].Pos.X += particles[i].Vel.X
|
particles[i].Pos.X += particles[i].Vel.X * deltaTime * 60 // Adjust for frame rate
|
||||||
particles[i].Pos.Y += particles[i].Vel.Y
|
particles[i].Pos.Y += particles[i].Vel.Y * deltaTime * 60
|
||||||
|
|
||||||
// Wrap around screen
|
// Wrap around screen
|
||||||
if particles[i].Pos.X < 0 {
|
if particles[i].Pos.X < 0 {
|
||||||
particles[i].Pos.X += float32(screenWidth)
|
particles[i].Pos.X += float32(screenWidth)
|
||||||
|
|
6
main.go
6
main.go
|
@ -24,7 +24,11 @@ func main() {
|
||||||
rl.SetWindowState(rl.FlagFullscreenMode)
|
rl.SetWindowState(rl.FlagFullscreenMode)
|
||||||
defer rl.CloseWindow()
|
defer rl.CloseWindow()
|
||||||
|
|
||||||
rl.SetTargetFPS(60)
|
refreshRate := rl.GetMonitorRefreshRate(monitor)
|
||||||
|
if refreshRate <= 0 {
|
||||||
|
refreshRate = 60 // Fallback to 60 if detection fails
|
||||||
|
}
|
||||||
|
rl.SetTargetFPS(int32(refreshRate))
|
||||||
|
|
||||||
InitBackground(rl.GetScreenWidth(), rl.GetScreenHeight())
|
InitBackground(rl.GetScreenWidth(), rl.GetScreenHeight())
|
||||||
|
|
||||||
|
|
159
transition.go
159
transition.go
|
@ -1,8 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
rl "github.com/gen2brain/raylib-go/raylib"
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,36 +22,54 @@ const (
|
||||||
|
|
||||||
type TransitionManager struct {
|
type TransitionManager struct {
|
||||||
active bool
|
active bool
|
||||||
startTime time.Time
|
|
||||||
phase TransitionPhase
|
|
||||||
direction TransitionDirection
|
direction TransitionDirection
|
||||||
oldStep int
|
|
||||||
newStep int
|
|
||||||
|
|
||||||
outFadeScaleDuration time.Duration
|
oldStep int
|
||||||
outSlideDuration time.Duration
|
newStep int
|
||||||
inFadeScaleDuration time.Duration
|
|
||||||
|
// 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 {
|
func NewTransitionManager() *TransitionManager {
|
||||||
return &TransitionManager{
|
return &TransitionManager{
|
||||||
outFadeScaleDuration: 150 * time.Millisecond,
|
totalSec: 0.6, // e.g., entire transition 600ms
|
||||||
outSlideDuration: 200 * time.Millisecond,
|
fadeFrac: 0.3, // 30% of total time for fade out scale
|
||||||
inFadeScaleDuration: 150 * time.Millisecond,
|
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) {
|
func (t *TransitionManager) Start(oldStep, newStep int) {
|
||||||
t.active = true
|
t.active = true
|
||||||
t.startTime = time.Now()
|
t.accumSec = 0
|
||||||
t.phase = TransitionOutFadeScale
|
|
||||||
t.oldStep = oldStep
|
t.oldStep = oldStep
|
||||||
t.newStep = newStep
|
t.newStep = newStep
|
||||||
|
|
||||||
if newStep > oldStep {
|
if newStep > oldStep {
|
||||||
t.direction = DirectionForward
|
t.direction = DirectionForward
|
||||||
} else {
|
} else {
|
||||||
t.direction = DirectionBackward
|
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 {
|
func (t *TransitionManager) IsActive() bool {
|
||||||
|
@ -65,80 +81,103 @@ func (t *TransitionManager) GetPhase() TransitionPhase {
|
||||||
if !t.active {
|
if !t.active {
|
||||||
return TransitionNone
|
return TransitionNone
|
||||||
}
|
}
|
||||||
elapsed := time.Since(t.startTime)
|
|
||||||
total := t.outFadeScaleDuration + t.outSlideDuration + t.inFadeScaleDuration
|
|
||||||
|
|
||||||
if elapsed >= total {
|
// Determine the linear progress
|
||||||
return TransitionNone
|
p := t.accumSec / t.totalSec
|
||||||
} else if elapsed < t.outFadeScaleDuration {
|
if p < t.fadeEnd {
|
||||||
return TransitionOutFadeScale
|
return TransitionOutFadeScale
|
||||||
} else if elapsed < t.outFadeScaleDuration+t.outSlideDuration {
|
} else if p < t.slideEnd {
|
||||||
return TransitionOutSlide
|
return TransitionOutSlide
|
||||||
} else {
|
} else {
|
||||||
return TransitionInFadeScale
|
return TransitionInFadeScale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TransitionManager) Update() (oldAlpha float32, oldScale float32, oldOffsetX float32,
|
// Easing function: "easeInOutCubic" => pronounced slow start, fast middle, slow end
|
||||||
newAlpha float32, newScale float32, newOffsetX float32) {
|
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 {
|
if !t.active {
|
||||||
return 1.0, 1.0, 0.0, 1.0, 1.0, 0.0
|
return 1, 1, 0, 1, 1, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed := time.Since(t.startTime)
|
// Accumulate variable time
|
||||||
totalDuration := t.outFadeScaleDuration + t.outSlideDuration + t.inFadeScaleDuration
|
dt := rl.GetFrameTime() // in seconds
|
||||||
if elapsed >= totalDuration {
|
t.accumSec += dt
|
||||||
// Transition done
|
if t.accumSec >= t.totalSec {
|
||||||
t.active = false
|
t.active = false
|
||||||
return 1.0, 1.0, 0.0, 1.0, 1.0, 0.0
|
return 1, 1, 0, 1, 1, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
oldAlpha = 1.0
|
oldAlpha, oldScale, oldOffsetX = 1, 1, 0
|
||||||
oldScale = 1.0
|
newAlpha, newScale, newOffsetX = 1, 1, 0
|
||||||
oldOffsetX = 0.0
|
|
||||||
newAlpha = 1.0
|
|
||||||
newScale = 1.0
|
|
||||||
newOffsetX = 0.0
|
|
||||||
|
|
||||||
slideDirection := float32(-1)
|
slideDir := float32(-1)
|
||||||
if t.direction == DirectionBackward {
|
if t.direction == DirectionBackward {
|
||||||
slideDirection = 1
|
slideDir = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if elapsed < t.outFadeScaleDuration {
|
p := t.accumSec / t.totalSec
|
||||||
// Phase 1: Out Fade/Scale
|
if p > 1 {
|
||||||
progress := float32(elapsed.Milliseconds()) / float32(t.outFadeScaleDuration.Milliseconds())
|
p = 1
|
||||||
oldAlpha = 1.0 - 0.2*progress
|
}
|
||||||
oldScale = 1.0 - 0.1*progress
|
|
||||||
|
|
||||||
// New tab not visible at all yet
|
globalP := easeInOutCubic(p)
|
||||||
newAlpha = 0.0
|
|
||||||
|
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
|
newScale = 0.9
|
||||||
newOffsetX = float32(rl.GetScreenWidth()) * slideDirection
|
newOffsetX = float32(rl.GetScreenWidth()) * slideDir
|
||||||
} else if elapsed < t.outFadeScaleDuration+t.outSlideDuration {
|
|
||||||
// Phase 2: Slide out old, slide in new
|
} else if p < t.slideEnd {
|
||||||
phaseElapsed := elapsed - t.outFadeScaleDuration
|
gStart := easeInOutCubic(t.fadeEnd)
|
||||||
progress := float32(phaseElapsed.Milliseconds()) / float32(t.outSlideDuration.Milliseconds())
|
gEnd := easeInOutCubic(t.slideEnd)
|
||||||
|
gRange := gEnd - gStart
|
||||||
|
subE := float32(0)
|
||||||
|
if gRange > 0 {
|
||||||
|
subE = (globalP - gStart) / gRange
|
||||||
|
}
|
||||||
|
|
||||||
oldAlpha = 0.8
|
oldAlpha = 0.8
|
||||||
oldScale = 0.9
|
oldScale = 0.9
|
||||||
oldOffsetX = -float32(rl.GetScreenWidth()) * progress * slideDirection
|
oldOffsetX = -float32(rl.GetScreenWidth()) * subE * slideDir
|
||||||
|
|
||||||
newAlpha = 0.8
|
newAlpha = 0.8
|
||||||
newScale = 0.9
|
newScale = 0.9
|
||||||
newOffsetX = float32(rl.GetScreenWidth()) * (1.0 - progress) * slideDirection
|
newOffsetX = float32(rl.GetScreenWidth()) * (1 - subE) * slideDir
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Phase 3: In Fade/Scale
|
gStart := easeInOutCubic(t.slideEnd)
|
||||||
phaseElapsed := elapsed - t.outFadeScaleDuration - t.outSlideDuration
|
gEnd := easeInOutCubic(1)
|
||||||
progress := float32(phaseElapsed.Milliseconds()) / float32(t.inFadeScaleDuration.Milliseconds())
|
gRange := gEnd - gStart
|
||||||
|
subE := float32(0)
|
||||||
|
if gRange > 0 {
|
||||||
|
subE = (globalP - gStart) / gRange
|
||||||
|
}
|
||||||
|
|
||||||
oldAlpha = 0.0
|
oldAlpha = 0
|
||||||
oldScale = 0.9
|
oldScale = 0.9
|
||||||
oldOffsetX = -float32(rl.GetScreenWidth()) * slideDirection
|
oldOffsetX = -float32(rl.GetScreenWidth()) * slideDir
|
||||||
|
newAlpha = 0.8 + 0.2*subE
|
||||||
newAlpha = 0.8 + 0.2*progress
|
newScale = 0.9 + 0.1*subE
|
||||||
newScale = 0.9 + 0.1*progress
|
newOffsetX = 0
|
||||||
newOffsetX = 0.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldAlpha, oldScale, oldOffsetX, newAlpha, newScale, newOffsetX
|
return oldAlpha, oldScale, oldOffsetX, newAlpha, newScale, newOffsetX
|
||||||
|
|
Loading…
Add table
Reference in a new issue