|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
devkitSMS tip: how to prioritize SFXs
Posted: Fri Dec 09, 2016 1:23 pm
|
It is known that PSGlib audio library includes support for replaying an SFX on top of the background music but it does a very basic job when it comes to start a new SFX when one is already playing: the library will simply stop the currently playing SFX to reproduce the newly requested one. Sometimes this might not be the desired behavior as in some cases the already playing SFX is of importance and we might prefer not to give way to a less important SFX.
So here follows a possible approach to a simple solution for this problem: we’re going to create a priority system that implements a way for an SFX to interrupt an already playing SFX only if the latter isn’t more important. First, we define a few priority levels, according to our needs. In this example I’ll create only 3 of them: #define PRIORITY_HIGH 70
#define PRIORITY_NORMAL 50 #define PRIORITY_LOW 30 note that the specific values aren’t important, as long as they fit in a single byte and they’re decreasing with the decreasing priority. Also, you can leave some unused values in between in case you need to create some intermediate priority levels. [Note: I tend not to use C enumerations because of the inconsistent behavior among compilers, so I choose to use a few #defines instead] Then, we need a variable to keep track of the priority of the currently playing SFX. Also, I’d expect a game using music and SFXs to require ROM paging, so we also need two variables to keep track of the bank locations of the currently playing SFX and of the currently playing background tune: unsigned char current_SFX_priority;
unsigned char current_SFX_ROM_bank; unsigned char current_tune_ROM_bank; Finally, we need a short macro that will start a SFX only when appropriate, which means either when there isn’t any other SFX playing or when the SFX currently playing isn’t of higher priority. It will also store the SFX bank location, if it’s started. #define FIRESFX(which,bank,how,prio) \
if((!PSGSFXGetStatus())||((prio)>=current_SFX_priority)){ \ PSGSFXPlay ((which),(how)); \ current_SFX_ROM_bank=bank; \ current_SFX_priority=prio; \ } So we’re now ready to use our newly created macro. The parameters needed for the macro invocation are: * A pointer to the SFX we want to play * The bank where the said SFX resides * The channels the SFX will use (SFX_CHANNEL2, SFX_CHANNEL3, SFX_CHANNELS2AND3 – this value will be passed untouched to PSGSFXPlay function) * The priority for this effect For example, say we’ve got an explosion SFX and some other important SFX; we might want to start the important SFX using: FIRESFX(important_SFX_psg, important_SFX_psg _bank, SFX_CHANNELS2AND3, PRIORITY_HIGH);
so that when it will happen that we need to fire the explosion SFX: FIRESFX(explosion_SFX_psg, explosion_SFX_psg_bank, SFX_CHANNEL3, PRIORITY_NORMAL);
this will or won’t actually be fired, as appropriate. We shouldn’t forget anyway that to make music and SFX work correctly, somewhere in our main game loop we need to constantly execute this, once per frame: SMS_mapROMBank(current_tune_ROM_bank);
PSGFrame(); SMS_mapROMBank(current_SFX_ROM_bank); PSGSFXFrame(); …but that was already a PSGlib requirement, anyway. I hope you found this small tip clear, interesting an useful. Feedback and comments welcome! |
|