Gameplay actions that don't need to be done every frame

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Gameplay actions that don't need to be done every frame

Post by DRW »

To reduce the CPU usage of a game, I thought of gameplay actions that don't need to be done in every frame.

Obviously, controller input as well as reacting to the controller input gets done every frame. When the player moves, stops or uses a weapon, this is done instantly.

But collision checks might not necessarily be done in every frame. If the player touches an opponent, he will most likely still touch it in the next frame.
So, we can use, for example, the odd frames to check the collision between the player and all opponents and hostile weapons.
And we can use the even frames for collision checks between the player's weapon and the opponents.

By the way, how often do commercial games do these checks? Do they check for collision every frame? Every two frames? Every four?
I remember that in "Super Mario Bros. 3", a turtle shell once went right through Mario without killing him.


Do you have any other ideas of general gameplay actions that can be suspended for one or more frames?

(Or other ideas to even out the CPU usage? For example, one idea is that an opponent either loads a new movement pattern or acts on the current pattern, but never loads a new pattern and does the first pattern action in the same frame.)
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Gameplay actions that don't need to be done every frame

Post by tokumaru »

Mega Man is a game that comes to mind - IIRC, enemies (maybe all objects?) check for collisions with other objects every other frame, and each object decides whether to do it by comparing the parity of the object slot it occupies with the parity of the global frame counter, to spread the CPU power between objects in even and odd slots.

I've been using this approach for some things too, even for things that happen less often. One thing that definitely doesn't have to happen every frame is objects testing whether they should be deactivated due to being too far from the camera. I think I have this one being done every 8 frames or so.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Gameplay actions that don't need to be done every frame

Post by tepples »

Some enemy move routines in the Haunted games and Full Quiet XOR the actor ID with the game tick count to find on which ticks to do things that are expensive in CPU time, such as scanning the terrain for platforms to jump to. This is similar to what tokumaru described.

Code: Select all

txa
eor game_ticks
and #%111
bne @notMyTurn
  ; do expensive calculation
@notMyTurn:
Full Quiet has a lot more enemies in play at any given time than the Haunted games (up to 9 vs. 5). It introduces "terrain dead reckoning", in which some enemies call the terrain reading and ejection routine only on every second tick unless moving faster than 3 pixels per tick.

Full Quiet also introduces "frameskip". Occasionally, lag frames occur, such as if there are many terrain-sensitive enemies in an area with complex terrain combined with rapid diagonal camera movement. If the engine detects that a lag frame has occurred (move + draw taking longer than 29780 cycles), it skips the next draw phase, instead doing move-move-draw to catch up. This way, the game can smoothly switch between a usual 60 fps and momentary 30 fps with far less chance of visibly slowing down.
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Gameplay actions that don't need to be done every frame

Post by nesrocks »

Ninja Gaiden also alternates some functions https://twitter.com/upsilandre/status/1 ... 3353050114
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Gameplay actions that don't need to be done every frame

Post by tokumaru »

tepples wrote: Tue Sep 20, 2022 5:55 pmThis is similar to what tokumaru described.
This is EXACTLY what I described. :lol:
If the engine detects that a lag frame has occurred (move + draw taking longer than 29780 cycles), it skips the next draw phase, instead doing move-move-draw to catch up. This way, the game can smoothly switch between a usual 60 fps and momentary 30 fps with far less chance of visibly slowing down.
That's a cool idea! I had thought of doing something similar in my Raycaster, where the drawing typically takes much longer than the game logic... the engine would run 2 or 3 logic steps in a row to try and catch up if drawing got really slow. I never considered doing this in more typical games though... I suppose you could indeed squeeze some extra time out of the CPU by skipping all display logic for a frame.

You have to be careful though, because unlike in a Raycaster, where the picture is entirely redrawn every frame, typical games update the background only a bit each time, so if an object needs to make changes to the background (e.g. a bomb destroying some blocks), it will need some extra logic to deal with this action happening in a frame where video updates will not happen... maybe delaying only the background update until it can be done, or even delaying the action itself. Scrolling is another thing to worry about, because if you accumulate a scrolling distance larger than what your scrolling engine can handle, the camera will noticeably lag behind if the heavy CPU load persists for several frames. To avoid this, you may have to limit the camera movement per logic frame to half of what your scrolling engine can handle.
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Gameplay actions that don't need to be done every frame

Post by Oziphantom »

you only need to run background collision every time they cross <smallest size of your tiles> boundary.

Hard to know what can be spread without knowing the full details of you game and code.
but yeah entities can be spread over, collision on a boundary change.
Animation, if you do things in 4 frames than you can just count every 4 frames rather than frames so you only update the system on every 4 frames etc
and level timers or mission timers one every 60 frames
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: Gameplay actions that don't need to be done every frame

Post by Fiskbit »

Zelda 1 has an interesting strategy where enemies all spawn 1 frame apart, which spreads out their background collision checks so they usually don't all happen on the same frame.
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Gameplay actions that don't need to be done every frame

Post by Ben Boldt »

Music would tend to work well at a lower update rate. If you were trying to do something like vibrato, you may start to hear it becoming "pixelated", which may or may not be a good thing (usually not).
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gameplay actions that don't need to be done every frame

Post by DRW »

Thanks for your suggestions.

tokumaru wrote: Tue Sep 20, 2022 3:37 pm IIRC, enemies (maybe all objects?) check for collisions with other objects every other frame, and each object decides whether to do it by comparing the parity of the object slot it occupies with the parity of the global frame counter, to spread the CPU power between objects in even and odd slots.
In my game, I have up to two players. So, I do two related things here:
First, the assignment of HeroA and HeroB to CurrentPrimaryHero and CurrentSecondaryHero switches after each frame. And then the even enemy slots check only for CurrentPrimaryHero while the odd slots check for CurrentSecondaryHero.

I'm thinking about whether I can do the check only every fourth frame. For character to character collision, this might work. But weapons are a bit faster. And the hero's sword shows each of its three animation phases for three frames each, so it might happen quite often that an enemy who actually got hit with one of the the outermost animation phases doesn't get attacked.

tokumaru wrote: Tue Sep 20, 2022 3:37 pm I've been using this approach for some things too, even for things that happen less often. One thing that definitely doesn't have to happen every frame is objects testing whether they should be deactivated due to being too far from the camera. I think I have this one being done every 8 frames or so.
This is something that I have to do every frame. In my game, characters can never be partially out of screen, to reduce the complexity of sprite rendering. (Otherwise I'd have to check every hardware sprite against the character's original x and y position to see whether some kind of overflow happens.) And not checking this every frame means we would have characters disappear on one side and reappear on the other.
Also, unlike collision checks, this one is pretty simple anyway, so there's not much to gain if we reduce it:
if x > 240 || y > StatusBarPosition then CharacterType = None.

Oziphantom wrote: Wed Sep 21, 2022 11:01 pm you only need to run background collision every time they cross <smallest size of your tiles> boundary.
Sure, this is something that is done anyway: If newX / 16 = currentX / 16, then horizontal movement is definitely possible.
Although this is a general check in the background collision routine and not specifically anything related to the idea of "check this only every two frames".

Oziphantom wrote: Wed Sep 21, 2022 11:01 pm Hard to know what can be spread without knowing the full details of you game and code.
Just imagine any random top-down game, like "Zelda" or "Commando". I guess whatever counts for these games in this regard can be used for mine as well.

Oziphantom wrote: Wed Sep 21, 2022 11:01 pm Animation, if you do things in 4 frames than you can just count every 4 frames rather than frames so you only update the system on every 4 frames etc
Animations are surely updated only every n frames, but not for all characters equally. You don't want every enemy to change its animation phase in perfect alignment, but of course based on when they appeared on the screen, when they stopped etc.

Oziphantom wrote: Wed Sep 21, 2022 11:01 pm and level timers or mission timers one every 60 frames
This is something where the update is more within the actual algorithm itself:

Code: Select all

if (--SubSecondsCounter == 0)
{
    if (--SecondsCounter == 0)
        DoTheStuff();
    else
        SubSecondsCounter = 60;
}
Not so much something where I can spread out the calculation to every second, fourth, eighth or 60th frame on a global basis.
Or do you have a specific optimization in mind?

Fiskbit wrote: Wed Sep 21, 2022 11:47 pm Zelda 1 has an interesting strategy where enemies all spawn 1 frame apart, which spreads out their background collision checks so they usually don't all happen on the same frame.
How often do they do the collision check?
And let's say they check every fourth frame or so: Why didn't they simply decide that the checks are done based on their character slot? Wouldn't this have been equally effective?

Ben Boldt wrote: Thu Sep 22, 2022 9:50 am Music would tend to work well at a lower update rate.
I don't know. In this case, I'd have to tell my composer to compose music twice as fast, so that it sounds normal when played only every second frame. I'm not sure whether this would be such a wise decision.


So far, all my spreading out is collision-based:
Opponent with hero weapon
Opponent with hero
Opponent weapon with hero
Item with hero
Item with hero weapon
Hero weapon with destroyable background tile

If you have any other, non-collision ideas what actions can be spread out over multiple frames, I'd be open for suggestions.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Gameplay actions that don't need to be done every frame

Post by Ben Boldt »

DRW wrote: Sun Oct 02, 2022 10:51 am
Ben Boldt wrote: Thu Sep 22, 2022 9:50 am Music would tend to work well at a lower update rate.
I don't know. In this case, I'd have to tell my composer to compose music twice as fast, so that it sounds normal when played only every second frame. I'm not sure whether this would be such a wise decision.
You can tell your composer to write the scores using only even numbers of frame delays. Then it would be easy for you to scale that.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gameplay actions that don't need to be done every frame

Post by DRW »

Nah! Music is something essential. I wouldn’t want to limit the compositional creativity for some optional optimization process.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Gameplay actions that don't need to be done every frame

Post by Ben Boldt »

DRW wrote: Mon Oct 03, 2022 8:12 am Nah! Music is something essential. I wouldn’t want to limit the compositional creativity for some optional optimization process.
Then why update only once per frame? How did that become the sweet spot for you?

I thought that Sunsoft Shanghai II does music updates every 2nd frame for some reason. (Not confirmed.) It is one of the very best soundtracks in my opinion, complete with vibratos.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gameplay actions that don't need to be done every frame

Post by DRW »

Ben Boldt wrote: Mon Oct 03, 2022 9:26 am Then why update only once per frame? How did that become the sweet spot for you?
That question is strange. I do this because the entire game runs on a frame by frame basis. Why should I update the sound more than once per frame?
Musicians compose their songs in FamiTracker. And NES libraries like FamiTone convert the song and expect their update function to run once per frame.
Only updating every second frame is an optimization, sure. Although I decided against it. But what sense does adding more work per frame make?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Gameplay actions that don't need to be done every frame

Post by Ben Boldt »

DRW wrote: Mon Oct 03, 2022 10:38 am
Ben Boldt wrote: Mon Oct 03, 2022 9:26 am Then why update only once per frame? How did that become the sweet spot for you?
That question is strange. I do this because the entire game runs on a frame by frame basis. Why should I update the sound more than once per frame?
Musicians compose their songs in FamiTracker. And NES libraries like FamiTone convert the song and expect their update function to run once per frame.
Only updating every second frame is an optimization, sure. Although I decided against it. But what sense does adding more work per frame make?
You said that music updates once per 2 frames (30 Hz) would be a sacrifice versus updating every frame (60Hz). So, my question was, if 30Hz updates are worse than 60Hz updates, why would it not be better to update the music engine at 120Hz? Or 1000 Hz? You could use a timer interrupt and update your music engine any rate you want. If CPU usage is not worth even considering to you when it comes to music updates, Why is 60 Hz so special. Why not go ahead and double it to 120 with that logic. Or just a little more or less, 48 Hz, 67 Hz. That is my question for you. 60Hz happens to already be the perfect tradeoff? Specifically, I want to understand how you so quickly dispose my idea.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gameplay actions that don't need to be done every frame

Post by DRW »

Ben Boldt wrote: Mon Oct 03, 2022 11:08 am You said that music updates once per 2 frames (30 Hz) would be a sacrifice versus updating every frame (60Hz). So, my question was, if 30Hz updates are worse than 60Hz updates, why would it not be better to update the music engine at 120Hz? Or 1000 Hz?
Because I'm still trying to find ways to decrease the CPU load, not to increase it.
If there's a thing that I could reduce by 50 %, but decide to keep it at 100 % for certain reasons, there's still no reason to change the working solution and increase it to 200 % just for shits and giggles.


Technical answers:


"Why don't you want to update the music only every second frame?"

Because the library is built to be updated once per frame. That's the intended use set forth by the developer of FamiTone. (I.e. the song in the game sounds the same as in FamiTracker when updated once per frame.)

Because decreasing the update would add artificial limitations for the composer, and his FamiTracker output wouldn't be identical to the way the song appears in the game, so he always has to compose first and then adjust afterwards. And you'd have to adjust all the FamiTracker songs manually between "I want to hear the song in FamiTracker now" mode and between "I want to convert the file for the ROM now" mode.
Also, he'd have to rewrite all the songs that he already finished.

Because it might introduce issues when the background music is mixed with sound effects.

Because sound effects also have to abide by the new rules.

Because music is essential stuff. I don't read controllers just every two frames. I don't do PPU updates only every two frames. I don't just set the scrolling every two frames.
I want to find ways to spread unimportant stuff over multiple frames, not the stuff that you literally experience every single moment of the game.
Collision checks are one thing. It doesn't matter whether a collision with an opponent is registered one frame earlier or later. It's not like that one additional frame would give you a noticeable way to avoid an attack. But the entire sound library is something that I don't want to compromise.


"Then why do you want to keep the music at once per frame? Why don't you change it to update twice per frame?"

Why should I?
I do understand the idea to fiddle with the library to make the code faster. But why should I ever fiddle with the library, using it in unintended ways, potentially introducing buggy behavior and making the composer's job harder, just so that I lose precious CPU time?

If I decide against "fiddling with the library to make it faster", the next logical step is not "fiddling with the library to intentionally make it slower".
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Post Reply