avaraline / Avara

Port of the original 1996 game from Ambrosia Software.
MIT License
123 stars 19 forks source link

Changing frame time in the middle of a game conundrum #191

Closed rherriman closed 3 years ago

rherriman commented 3 years ago

As of right now, it is possible to manually change a game's frame time in the middle of a game. We also have discussed the possibility of higher LTs automatically ratcheting up to higher frame times (16ms -> 32ms -> 64ms).

This has presented a problem, however, with certain game-play objects as they are currently written. For example, if a grenade is armed at one frame time and fired at another, it does not behave correctly--the gravity and friction could be much higher or lower than it is meant to be. These issues can be rectified by changing when the FPS coefficients are calculated, but it means performing those calculations every frame as opposed to simply during initialization of the object.

We need to decide whether or not to restrict changing frame time mid-game (including after LT changes), or keeping that possibility open by committing to revisiting the updated game-play code and performing FPS coefficient calculations every frame.

rherriman commented 3 years ago

Here's an example of the type of modification needed in order to continue to support switching frame times mid-game: https://github.com/avaraline/Avara/commit/c9dfd48da80648f75b7e45a82e8b3ff6deb2be3f

If we decide to ditch that functionality, the above change ought to be reverted for efficiency.

tra commented 3 years ago

I have developed what seems to be a pretty easy way to make Actors work at different frame rates. Check out 163b5fd for details. The quick version is that you stick variables you want to work across frame-rate changes in a method named ResumeScript().

The longer version is that there was already a method called ResumeLevel() that is called any time a level is resumed. Generally that method does certain actions such resuming sounds. But the ResumeScript() method is intended to be more similar to the BeginScript() and EndScript() methods except that is run on both game start and game resume. So ResumeScript() is the place to set any variables that might change during a game pause (e.g. anything that depends onframeTime).

rherriman commented 3 years ago

The call to ResumeScript at the top of CGrenade::Arm are to initialize the values, right? And the method ultimately gets called again if the game is ever paused and resumed?

If so, I think this is a good solution, though I’d rather rename the method to something clearer—it’s appearance at the top of CGrenade::Arm is a little confusing. Something similar to AdjustForFps would be clear when appearing in both ResumeLevel and CGrenade::Arm.

tra commented 3 years ago

Barring any other discovered bugs, I believe this works now. Thanks to the use of AdaptableSettings() methods you can now change frame times in the middle of a game an everything continues on pretty much as expected.