Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop the timer when the game is not visible #478

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

LeonardoBraga
Copy link

@LeonardoBraga LeonardoBraga commented Jun 13, 2019

Use the Page Visibility API to allow for pausing/resuming the game timer.

Closes #477

requestAnimationFrame(() => {
this.base!.textContent = minSec(Date.now() - this._start!);
this.base!.textContent = minSec(++this._secondsSinceStart! * 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that setInterval is accurate, but it isn't.

The correct way to do this (afaik):

  • _start becomes _anchorTime.
  • On _startTimer, set _anchorTime to Date.now() & start the interval.
  • When visibility becomes hidden, clear the interval, and set _hiddenTime to Date.now().
  • When visibility becomes visible, increase _anchorTime by Date.now() - _hiddenTime, and restart the interval.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, @jakearchibald. In my initial tests, I noticed that Chrome does account for the discrepancies in the setInterval by offsetting the next "tick" by enough milliseconds to compensate for the previous ones, but indeed the users of other browsers would get ~1s of unfair advantage every ~16m.

I applied the fixes as you requested.

Copy link
Contributor

@jakearchibald jakearchibald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting there!

src/services/preact-canvas/components/top-bar/index.tsx Outdated Show resolved Hide resolved
src/services/preact-canvas/components/top-bar/index.tsx Outdated Show resolved Hide resolved
src/services/preact-canvas/components/top-bar/index.tsx Outdated Show resolved Hide resolved
@LeonardoBraga LeonardoBraga force-pushed the issue-477 branch 2 times, most recently from 1dcf970 to 5489b3d Compare June 17, 2019 14:30
Copy link
Contributor

@jakearchibald jakearchibald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with all the code here, however pausing is only fixed for the timer across the top, and isn't reflected in the final time when you win.

if (gameChange.playMode! === PlayMode.Playing) {
- here's where the real game timer is.

Having timer logic split across two places isn't great. We were trying to avoid going through DOM diffing every second, which was a bit slow on lower end phones.

I'm open to better ideas, but here's the best I've got right now:

  • Make anchorTime part of Game's state.
  • Make anchorTime a prop on TopBar.
  • Move the visibilityChanged logic into Game, and use it to set the timerRunning prop on TopBar.

@LeonardoBraga we really appreciate the time you've spent on this so far, and totally understand if you want us to take on the rest. Let us know.

@LeonardoBraga
Copy link
Author

Hey @jakearchibald, are you kidding? :-) We should definitely do it in the best way we possibly can!

I had noticed the main timer when I was analyzing the code but I just wasn't sure if I should have gone for a PR what would touch multiple parts of the app, this is why I went for the low hanging fruit. I'm glad you're open to a more thorough change and will take a deeper look at your suggestion, the code, and work on the next iteration.

@jakearchibald
Copy link
Contributor

We've changed the build for this project which has involved moving a lot of files around. Don't worry about the conflicts, we'll take care of it when we come to merge this.

@LeonardoBraga
Copy link
Author

Sure, thanks for the update. I apologize for the radio silence over the last days, things ended up piling up on my end. I plan on wrapping the modifications you requested this week and send for your review.

@LeonardoBraga
Copy link
Author

@jakearchibald I tried to incorporate the points you raised before, and besides any other feedback you may have, I wanted to call your attention to the following items:

  • I've re-used completeTime to display the partial timer and removed endTime, which wasn't being used. Let me know if you'd rather a different state field.
  • I've added a switch case "fall through" to save some bytes in the final bundle by avoiding another call to stopTimer and a break. I know it's an unpopular approach, to say the least, so just say the word and I'll remove it.

@LeonardoBraga
Copy link
Author

Hey @jakearchibald, just wanted to know if you had time to check out the latest changes and have any additional feedback. Thanks! :)

@jakearchibald
Copy link
Contributor

Thanks for continuing with this, and sorry for the slow response.

This is now doing the DOM-diffing every second, which we were trying to avoid due to performance issues on low-end devices. I'll try and think of a way around it.

Base automatically changed from master to main February 26, 2021 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pause the timer when the game is hidden
2 participants