added variable refresh rate support

This commit is contained in:
partisan 2024-12-21 09:33:30 +01:00
parent 84fe6fe9eb
commit f75618ec44
3 changed files with 113 additions and 67 deletions

View file

@ -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)

View file

@ -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())

View file

@ -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 oldStep int
newStep int newStep int
outFadeScaleDuration time.Duration // Single total transition duration (seconds)
outSlideDuration time.Duration totalSec float32
inFadeScaleDuration time.Duration
// 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