I quite like the idea of a different FPS for the draw event, that's not actually that hard.
Awesome! Ready by Monday?
Sorry! But yeah, what I was trying to say near the end of my first post was that I'm sure GMS is designed in such a way that it's internals are not too dependent on the Step & Draw events being coupled (rather than the haphazard way some of us users may allow a stray update in our 'Draw' code!). So I'm hopeful that it wouldn't be too much of a mammoth task to split the events & basically have 2 separate timing loops which trigger them.
I suspect it would have to be a multiplier of the step (or other way round - whatever). ...(snip)...
Yeah, I sort of agree that if we (as GMS users) want to define a fixed "draw_speed" (one of the 3 modes I suggested), we might prefer to set both it & the room_speed so that one divides nicely into the other where possible. As mentioned, I think the main use of that facility would be to allow a game to set it's draw_speed to match the display refresh rate. That works easily for say, room_speed=30, and then draw_speed=30 (for low-spec devices) or 60 (for better specs). With vsync enabled, we'd then be guaranteed a whole number of Step events between each Draw, and no tearing.
( EDIT: But, it wouldn't actually matter if the two rates weren't nice factors/multipliers! See the bit after the next quote for why. )
Bear in mind here (in this mode, where we've defined a fixed draw_speed which differs to the room_speed, so we're ok to break backwards compatibility!), if the Draw events fall behind this specified fixed rate (device too busy or whatever), then they would be skipped as needed. Step events however would always be processed: if they fall behind, Draw events would be skipped until Step gets "in step" again!
( EDIT: And of course, it could work equally well the other way around, for high-update-rate physics, as you mention. )
The problem would be that if it wasn't, then eventually one of the events would suffer a delay due to the other one over running. For example, an FPS of 23 for step and 60 for rendering. This would mean than the drawing would at some point be delayed if the step needed to be run just before, and this could cause stuttering anyway.
OK, let's follow through on this thought, as it nicely highlights the main advantage of the approach (and indeed the reason I've used it elsewhere before)...
I think rather than designing a game with a room_speed of 23 (unusual, but it made a point!), this situation would be more typical of the draw_speed mode I mentioned where it would perform Draw events as fast as possible, so the render rate actually varies & definitely does not divide nicely into room_speed chunks! This would usually be for where you only care about maximum performance, with eg. room_speed=30 or 60 or whatever, and possibly vsync disabled (though could be enabled to cap it to display refresh rate). But it would equally apply for eg. room_speed=60 & draw_speed=144 (capped with vsync for a 144Hz monitor)
So GMS triggers Draw events as fast as possible. Now, like you say, sometimes in between Draw events, the game has to process another Step
just at the boundary before it would be due to process the
next one. In doing so, it slightly overruns the timer into what would be the next Step. Well, no problem... as described in my first proposal, we just process another Step immediately, before we trigger the next Draw event. Remember that the idea here is NOT that Draw events occur at regular intervals. Instead we (GMS users) can implement whatever tweening or similar we want in our Draw code (which is the intention by enabling this feature in the first place), in order to smooth out all motion. That next Draw event will be called at the very beginning of the tweened time period following that next Step, so there won't be much motion to tween yet, so it's not like everything on screen has moved 2 whole Steps at once. The important thing is that Step events are never skipped, and happen as regularly as possible, at the expense of Draw events when needed (since the tweening will smooth those out).
Picture this: delta_step = 0.0 through 1.0
- at 0.001 Draw would render everything as it was just after the
previous Step, step(n-1), at a point in time immediately after the current step(n) has been processed
- at 0.999 Draw would render everything tweened to just before it reaches the positions set by the current step(n)
- if delta_step >= 1.0, we process another Step, step(n+1), and subtract 1.0 from delta_step
In this way, on faster devices, you could have eg. 10 Draw events triggered in between each Step (at eg, delta_step = 0.1, 0.2, 0.3, etc.)
Or on slower devices, you could have multiple Step events processed in between each Draw event.
So those Draw events might be rendered at eg. Step times = 0.3, 1.6, 2.9, 4.2, 5.5, etc
So there it skips over 2 Step events (there's no 3.x in that example), but of course everything tweened on-screen only moves the same 1.3 Steps as for every other frame in that sequence, so the motion remains fluid throughout, no jerks/stutters.
Note, this explanation does highlight one slight drawback of tweening: that what you are rendering is typically somewhere between 0.0 and 1.0 Steps "behind" what the game has just processed. But in practice that's so slight, the added fluidity outweighs it, especially as the draw_speed increases.
If I were doing this in native code, I'd run each process on a separate thread, then pass over "new" drawing locations each step event. then the drawing code could tween nicely itself, and the process event would never hamper the drawing on as it was on a separate thread (assuming at least dual core). But that's currently not possible in GMS - and a WHOLE different conversation.
Absolutely, in an ideal world. But I'd never dream of suggesting GMS should support multi-threading for this kind of stuff, and it'd be complete overkill for most of us and our projects anyway!
There's no point in running graphics faster than 60fps (currently) as although there are the new GSync monitors, they are rare and aren't really catching on.
I'd actually be interested in figures on that if anyone has a reference. Steam's hardware survey doesn't seem to include Refresh Rate (any more, I believe it may have done in the past), unless I've overlooked it. Which could point to a very low take up of high refresh rate monitors since CRTs bit the dust.
I agree the GSync/Freesync displays are rare (& eye-wateringly expensive!), but there are certainly a lot of higher-than-60Hz displays out there for not much more $$$ than your standard 60Hz ones. Gamers who've adopted them seem to find it hard to go back to 60Hz, even perhaps at the expense of resolution or colour reproduction?
Anyway, I don't see any reason for game devs to exclude supporting higher refresh rates if it's not much trouble to do so. And it's certainly good practice to test on them.
If we could get something in place that supports independent Step/Draw rates, I don't suppose it matters what refresh rate it's targetting. It would just be more tweened/interpolated Draw events in between each Step. Should be flexible enough to support whatever. Whereas it's much trickier to support them with Step/Draw events locked together.
Hopefully that helps iron out a few more wrinkles
Happy to discuss/iterate further on it if anyone thinks there are any other gotchas / showstoppers?