Skip to main content

News

Topic: Frames skipped when moving from map to battle (Read 2163 times) previous topic - next topic

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Frames skipped when moving from map to battle
This seems like a map engine bug to me, so I'm posting it in Map Support, but I'm actually not positive.

I encountered a very strange issue after implementing random battle triggering in Specs: When a battle is triggered, a bunch of stuff is skipped, despite no actual lag occurring at all.  It appears there's some erroneous frame-skipping going on here for reasons I can't fathom...

Since this is a difficult issue to explain properly, here's a demo that illustrates the problem:
https://drive.google.com/file/d/0BxPKLRqQOUSNWC03Vk9VTWZfYms/view?usp=sharing

Stand around on the map for a bit, then try to trigger a battle.  Once the battle music starts, you'll see a variable number of frames skipped equal to the number of frames spent on the field.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Frames skipped when moving from map to battle
Reply #1
Well isn't this something.  I had forgotten all about it, but THIS was the issue that ultimately pushed me to make minisphere.  Sometime toward the end of 2014 I did eventually figure out the cause of this glitch: Sphere 1.5 has a bug in its FPS throttle code that causes it to skip seconds worth of frames if a script blocks during the main MapEngine() loop.

I actually don't know if this bug was fixed in later Sphere builds like 1.6, but in any case, here it is for posterity - the bug that convinced me Sphere 1.x needed to be replaced. :P
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Frames skipped when moving from map to battle
Reply #2

Well isn't this something.  I had forgotten all about it, but THIS was the issue that ultimately pushed me to make minisphere.  Sometime toward the end of 2014 I did eventually figure out the cause of this glitch: Sphere 1.5 has a bug in its FPS throttle code that causes it to skip seconds worth of frames if a script blocks during the main MapEngine() loop.


I encountered that bug all of the time. I eventually ended up caching the framerate before I go into a blocking loop and then I unthrottle the frame rate. Then when the loop has finished, I bring the framerate back to normal.

It's good to hear that this does not happen in minisphere.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Rahkiin
  • [*][*][*]
Re: Frames skipped when moving from map to battle
Reply #3
Maybe this is why i also had troubles timing stuff like -walk to player animated- (as in pokemon) in my game...

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Frames skipped when moving from map to battle
Reply #4
For those curious about the nature of the bug, I looked at the Sphere 1.x code again to refamiliarize myself with the issue.  The Sphere 1.x map engine includes a lot of code like this:

https://github.com/sphere-group/sphere/blob/master/sphere/source/engine/map_engine.cpp#L4720-L4721

Remember those two lines, I'll come back to them in a bit.  Sphere's frameloop works by predicting the time of the next frame.  If a render takes longer than that, subsequent frames are skipped (up to 20!) to make up the difference.  If instead the frameloop is ahead of schedule, the engine kills time until the wall time catches up.  Nothing too fancy, minisphere's frameloop works similarly.  However, Sphere's has a fatal flaw: It doesn't reset the timer after a skip.  Here's the core of the frameloop:

https://github.com/sphere-group/sphere/blob/master/sphere/source/engine/map_engine.cpp#L3957-L3973

Remember those two lines above?  m_NextFrame is reset when a script takes longer than 1000ms.  Except sometimes this isn't done (I don't remember the exact scenario that causes that), and that's where the problem starts.  The engine now thinks it's WAY behind schedule and tries to catch up by skipping frames.  Max frameskip is 20, so after 20 frames it should straighten itself out--except that the timer isn't reset during the skip, so it just keeps on skipping until it catches up.  Effectively you have infinite frameskip, with an odd flip thrown in every 20 frames each time the limit is hit.

This was the reason I wrote the minisphere frameloop the way I did.  All the frame management is centralized in FlipScreen(), so no matter how your control flow goes, no matter whether an update script blocks or not, the same timing logic is used for every flip so that the above is a non-issue.  There's never any need to detect blocking scripts because if, at any time, the frameskip limit is hit (in minisphere, 5 frames by default), the prediction can no longer be trusted and the engine resets it.

Here's minisphere's framerate management code.
https://github.com/fatcerberus/minisphere/blob/master/src/engine/screen.c#L329-L345

Take note of the last sentence in that comment.  better that we lag instead of never rendering anything at all.  Thanks a lot, buggy engine. :P
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Frames skipped when moving from map to battle
Reply #5
Another interesting thing I just noticed is that busy loop that synchronizes the framerate:
https://github.com/sphere-group/sphere/blob/master/sphere/source/engine/map_engine.cpp#L3964-L3968

It just spins in a while loop for a bit instead of sleeping nicely until the next frame like minisphere does.  Now I know why Sphere 1.5 was always such a CPU hog. :)
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Frames skipped when moving from map to battle
Reply #6
Well whaddyaknow. That looks like old style, yes.