joelschutz / stagehand

The only scene manager you will ever need for Ebitengine
MIT License
25 stars 5 forks source link

Transitions change direction for a short time #9

Open sedyh opened 1 month ago

sedyh commented 1 month ago

I'm not sure if anyone wrote about this, but all the transitions behave a little strange for me. It looks as if the direction of the transition smoothly changes like this: 0 -> 0.3 -> 0 -> 1, rather than 0 -> 1 where 0 is the scene A and 1 is the scene B, while the transition time under the hood goes strictly from 0 -> 1.

Its looks like this: Recording 2024-09-30 at 20 17 49

Lets take a look on a slower example: Recording 2024-09-30 at 21 39 51

Time is 0, alpha is 1: image Time is 0.1, alpha is 0.8: image Time is 0.2, alpha is 1 again: image Time is 0.75, alpha is 0.4: image

Its the code for transition between scene.Company and scene.Dark.

scene.Company ```go type Company struct { manager helper.CommonManager state helper.Common timer *time.Timer } func NewCompany() *Company { return &Company{} } func (s *Company) Load(state helper.Common, manager helper.CommonController) { s.manager = manager.(helper.CommonManager) s.state = state } func (s *Company) PostTransition(state helper.Common, from helper.CommonScene) { s.timer = time.NewTimer(helper.Active) } func (s *Company) PreTransition(from helper.CommonScene) helper.Common { return s.state } func (s *Company) Unload() helper.Common { return s.state } func (s *Company) Layout(w, h int) (int, int) { return w, h } func (s *Company) Update() error { if s.timer == nil { return nil } select { case <-s.timer.C: s.state.Next = NewTitle() s.manager.SwitchWithTransition(NewDark(), helper.CommonFade()) default: } return nil } func (s *Company) Draw(screen *ebiten.Image) { sw, sh := helper.Bounds(screen) screen.Fill(colornames.Black) face := &text.GoTextFace{Source: assets.FontSecondary, Size: 64} op := &text.DrawOptions{} str := "COMPANY" tw, th := text.Measure(str, face, face.Size) op.GeoM.Translate((sw-tw)/2, (sh-th)/2) op.ColorScale.ScaleWithColor(colornames.Orange) text.Draw(screen, str, face, op) } ```
scene.Dark ```go type Dark struct { manager helper.CommonManager state helper.Common timer *time.Timer } func NewDark() *Dark { return &Dark{} } func (s *Dark) Load(state helper.Common, manager helper.CommonController) { s.manager = manager.(helper.CommonManager) s.state = state } func (s *Dark) PostTransition(state helper.Common, from helper.CommonScene) { s.timer = time.NewTimer(helper.Silent) } func (s *Dark) PreTransition(from helper.CommonScene) helper.Common { return s.state } func (s *Dark) Unload() helper.Common { return s.state } func (s *Dark) Layout(w, h int) (int, int) { return w, h } func (s *Dark) Update() error { if s.timer == nil { return nil } select { case <-s.timer.C: s.manager.SwitchWithTransition(s.state.Next, helper.CommonFade()) default: } return nil } func (s *Dark) Draw(screen *ebiten.Image) { screen.Fill(colornames.Black) } ```
helper.Common* ```go type CommonTransition = stagehand.SceneTransition[Common] type CommonController = stagehand.SceneController[Common] type CommonManager = *stagehand.SceneManager[Common] type CommonScene = stagehand.Scene[Common] type Common struct { Next CommonScene } func NewSceneState(next CommonScene) Common { return Common{Next: next} } func CommonFade() CommonTransition { return stagehand.NewDurationTimedFadeTransition[Common](Transition) } func CommonSkip() CommonTransition { return stagehand.NewDurationTimedFadeTransition[Common](0) } var ( Active = 2 * time.Second Silent = 500 * time.Millisecond Transition = 5 * time.Second ) ```
sedyh commented 1 month ago

I guess it happends because isFadingIn suddenly becomes true where is shouldn't. It becomes "wrong" just after the transition and just before the next transition:

fade-out: scene-a -> scene-b
fade-out: scene-a -> scene-b
fade-out: scene-a -> scene-b
fade-in:  ! wrong one
fade-out: scene-b
fade-out: scene-b
fade-out: scene-b
fade-out: scene-b
fade-out: scene-b
fade-in:  ! wrong-one
fade-out: scene-b -> scene-c
fade-out: scene-b -> scene-c
fade-out: scene-b -> scene-c
joelschutz commented 3 weeks ago

As it seems, the problem may be the CalculateProgress function and its uses on the code. It's mainly used to calculate this tween for the transition. This must be the error.

I think the best action is to use a library dedicated to it with a better implementation like Gween. I'll try to implement the fix this week. This was a upgrade that I planned some time ago and eventually neglected.

sedyh commented 3 weeks ago

I think the best action is to use a library dedicated to it with a better implementation like Gween.

Idk, imo these scene transitions are the core functionality of the library, I won't be able to use it without it.

I'll try to implement the fix this week. This was a upgrade that I planned some time ago and eventually neglected.

Yeah, sure. Thanks.