Print Text on screen during gameplay

Aerisetta

Active member
Please see video example of narrator from dragons crown. The text appears at the bottom while it is spoken.

I want to create this effect. While the player is playing and fighting I will have voiced narration but I need subtitles as well. Currently I have to make an image per subtitle but i want to make a lot and was wondering if there was a ready made solution where I only need to provide a text string and it can be printed out like in Dragon's Crown. The text can appear all at once.

 
@Aerisetta Here's an example of what I said in my previous post. This way you can use narration as music maintaining the tracks playing, and control everything directly in the audio file.

Thanks for looking into it but the music is not actually the problem, infact I think openBOR has a setmusicvolume function I can use to duck the music track.

The problem I am facing is I want the narrator to keep speaking during combat. The combat sound effects is what is causing the problem.

in order to hear the narrator, I need to push the narration audio louder but it's technically already maxed out (all my sounds are maxed out 10 decibels gain cause that seems like the standard people have been using for all openbor games sounds)
 
Thanks for looking into it but the music is not actually the problem, infact I think openBOR has a setmusicvolume function I can use to duck the music track.

The problem I am facing is I want the narrator to keep speaking during combat. The combat sound effects is what is causing the problem.

in order to hear the narrator, I need to push the narration audio louder but it's technically already maxed out (all my sounds are maxed out 10 decibels gain cause that seems like the standard people have been using for all openbor games sounds)
Yeah, I had some sound/music volume issues in the past with SOR2X and the only thing that solved my problem was a complete volume readjustment for all audio files.
Similar to your case, I had all the audio file's volume at max and some sounds could not be heard because they were originally very low. So, I reduced all the volume by around 50% giving a range to make specific sounds louder than the others in order to be heard properly.
 
I tested this way and works well

Code:
anim follow1
        loop 0
        offset    0 30
    delay    5
       frame    data/chars/misc/empty.gif
    @cmd    settextobj 0 20 90  3 -1 "Objectives:" openborvariant("elapsed_time")+4000
    @cmd    settextobj 1 20 110 9 -1 "-_Defeat_all_enemies!" openborvariant("elapsed_time")+4000
       frame    data/chars/misc/empty.gif
       frame    data/chars/misc/empty.gif
       frame    data/chars/misc/empty.gif
 
Yeah, I had some sound/music volume issues in the past with SOR2X and the only thing that solved my problem was a complete volume readjustment for all audio files.
Similar to your case, I had all the audio file's volume at max and some sounds could not be heard because they were originally very low. So, I reduced all the volume by around 50% giving a range to make specific sounds louder than the others in order to be heard properly.
Thanks!

This is incredibly useful for me

@script
if(frame == 0)
{
int maxchannels = openborvariant("maxsoundchannels");
int channel;

//STOP ALL SAMPLE CHANNELS
for(channel = 0; channel < maxchannels; channel++){
stopchannel(channel);
}
}
@end_script
Do you mind helping me make this a function? because I actually need to use it a lot
 
Do you mind helping me make this a function? because I actually need to use it a lot

Create a text file with the following content and save it with a .c extension. Name it whatever you feel like, and put it wherever you want in the data folder, but I'd recommend somewhere in the scripts folder with a name that makes it easy to keep organized.

C:
void stop_all_playback()
{
    int max_channels = openborvariant("maxsoundchannels");
    int channel;

    /* Loop over each channel and stop playback. */
    for(channel = 0; channel < max_channels; channel++){
        stopchannel(channel);
    }
}

Add this to the top of any script file you want to use the function in, using your path and name from above. For models that call it on an animation frame, it goes in their animation script.

C:
#import "data/scripts/sounds_stop_all.c"

Now you can run the function on a frame, like this:

Code:
@cmd stop_all_playback
frame data/chars/dude/dude_0.png # Stop all sounds on this frame.

HTH,
DC
 
Last edited:
Create a text file with the following content and save it with a .c extension. Name it whatever you feel like, and put it whatever you want in the data folder, but I'd recommend somewhere in the scripts folder with a name that makes it easy to keep organized.

C:
void stop_all_playback()
{
    int max_channels = openborvariant("maxsoundchannels");
    int channel;

    /* Loop over each channel and stop playback. */
    for(channel = 0; channel < max_channels; channel++){
        stopchannel(channel);
    }
}

Add this to the top of any script file you want to use the function in, using your path and name from above. For models that call it on an animation frame, it goes in their animation script.

C:
#import "data/scripts/sounds_stop_all.c"

Now you can run the function on a frame, like this:

Code:
@cmd stop_all_playback
frame data/chars/dude/dude_0.png # Stop all sounds on this frame.

HTH,
DC
works perfectly, thank you! here's what my entity looks like now

Code:
name TextPop_C01-01
type panel
speed        10
facing 1
setlayer     999
shadow 0
animationscript        data/scripts/player.c




anim    idle
    loop    1
    delay    1000
    offset    0 0
    frame    data/chars/text/NarratorBox.gif
    @cmd    suicide
   
   
   
anim    follow1
    loop    0
    offset    0 0
    drawmethod    alpha 6
    drawmethod    channel 0.7
    @cmd    StopSounds
    delay    1
    frame    data/chars/text/NarratorBox.gif
    @cmd    TextClear 5
    @cmd    TextClear 6
    delay    800
    @cmd    TextPop "Upon_hearing_rumors_of_an_Artifact_hidden_within_these_long" 5 9 50 100 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    @cmd    TextPop "forgotten_ruins,_your_party_arrive_to_claim_it_for_yourselves." 6 9 50 130 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    sound    data/chars/text/C01-01A.wav
    frame    data/chars/text/NarratorBox.gif
    delay    1
    frame    data/chars/text/NarratorBox.gif
    @cmd    TextClear 5
    @cmd    TextClear 6
    @cmd    StopSounds
    frame    data/chars/text/NarratorBox.gif
    delay    800
    @cmd    TextPop "Unfortunately,_you_discover_the_Church's_agents_have_arrived" 5 9 50 100 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    @cmd    TextPop "before_you,_seeking_the_Artifact_for_their_own_purposes." 6 9 50 130 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    sound    data/chars/text/C01-01B.wav
    frame    data/chars/text/NarratorBox.gif
    delay    1
    @cmd    TextClear 5
    @cmd    TextClear 6
    frame    data/chars/misc/empty.gif
    @cmd    suicide
   
anim    follow2
    loop    0
    offset    0 0
    drawmethod    alpha 6
    drawmethod    channel 0.7
    delay    1
    @cmd    StopSounds
    frame    data/chars/text/NarratorBox.gif
    @cmd    TextClear 5
    @cmd    TextClear 6
    delay    800
    @cmd    TextPop "The_Church_of_Pure_Thoughts,_mighty_and_revered," 5 9 50 100 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    @cmd    TextPop "rules_over_the_spiritual_life_for_all_who_live_in_Earendyl." 6 9 50 130 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    sound    data/chars/text/C01-01C.wav
    frame    data/chars/text/NarratorBox.gif
    delay    1
    frame    data/chars/text/NarratorBox.gif
    @cmd    TextClear 5
    @cmd    TextClear 6
    @cmd    StopSounds
    frame    data/chars/text/NarratorBox.gif
    delay    800
    @cmd    TextPop "Harnessing_Divine_Magicks_bestowed_by_the_Church," 5 9 50 100 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    @cmd    TextPop "their_Priests_deliver_retribution_to_all_they_deem_'immoral'." 6 9 50 130 1000 # TextPop {text} {index} {font} {time} {x} {y} {z}
    sound    data/chars/text/C01-01D.wav
    frame    data/chars/text/NarratorBox.gif
    delay    1
    @cmd    TextClear 5
    @cmd    TextClear 6
    frame    data/chars/misc/empty.gif
    @cmd    suicide
 
That's not going to happen because it's not really an engine limit. Music streams directly from the disk. No matter how powerful your hardware is there's only so much throughput for that.

If you want multiple tracks then you need to use sound effects. The only difference is sound effects load to memory first. There's no limit to what you can play with them. IOW multiple music tracks are already supported. It's really more accurate to say you get 64 sound channels + one bonus streaming channel.

As for the overlap, I can't believe you used up all 64 at once. That's the same number an Xbox has. There’s something else going on and I suggest troubleshooting that instead of trying to reinvent the wheel. Maybe post up some of your sound trigger code / objects so we can take a look.

DC

@Aerisetta,

I was working on script playback functions, when I ran into the following and it remided me of this thread. It's the likely culprit for your sounds cutting off.

C:
#define        INT_TO_FIX(i)        ((unsigned int)i<<12)
#define        FIX_TO_INT(f)        ((unsigned int)f>>12)

I don't expect you to know what they mean, so here's the gist in a nutshell. They're for float/int conversions, and as is, it's not possible to get a value from them over 1,000000. Since they are used for the .wav loading buffer, that means .wav files exceeding one million bytes (just under one megabyte) get truncated. In practical terms that means sounds are limited to roughly 10 seconds, depending on the quality settings when you made the file.

I can see about amending this for future releases, but for now you'll need to do a workaround using a daisy chain playback:
  1. Divide the long track into a series smaller files. I'd go with 500KB each.
  2. Set up an array, and place the sound IDs as you load them into the array entry.
  3. Start a playback, and get the channel.
  4. Monitor the channel (in an update script), and as soon as the channel is inactive, start the next sound in your array. Get its channel.
  5. Repeat until you're at the last array element.
This will seamlessly play the divided sounds as a single track. There's no practical limit to the number of sounds you can load, so no worries about that. It would admittedly be very complex script. Then there's splitting the sound, but I'm sure there's tools out there that can do it quickly.

HTH,
DC
 
@Aerisetta,

I was working on script playback functions, when I ran into the following and it remided me of this thread. It's the likely culprit for your sounds cutting off.

C:
#define        INT_TO_FIX(i)        ((unsigned int)i<<12)
#define        FIX_TO_INT(f)        ((unsigned int)f>>12)

I don't expect you to know what they mean, so here's the gist in a nutshell. They're for float/int conversions, and as is, it's not possible to get a value from them over 1,000000. Since they are used for the .wav loading buffer, that means .wav files exceeding one million bytes (just under one megabyte) get truncated. In practical terms that means sounds are limited to roughly 10 seconds, depending on the quality settings when you made the file.

I can see about amending this for future releases, but for now you'll need to do a workaround using a daisy chain playback:
  1. Divide the long track into a series smaller files. I'd go with 500KB each.
  2. Set up an array, and place the sound IDs as you load them into the array entry.
  3. Start a playback, and get the channel.
  4. Monitor the channel (in an update script), and as soon as the channel is inactive, start the next sound in your array. Get its channel.
  5. Repeat until you're at the last array element.
This will seamlessly play the divided sounds as a single track. There's no practical limit to the number of sounds you can load, so no worries about that. It would admittedly be very complex script. Then there's splitting the sound, but I'm sure there's tools out there that can do it quickly.

HTH,
DC
Thx this could be quite useful for ambient sounds!
 
Thx this could be quite useful for ambient sounds!

I couldn't resist after your other post about ChatGPT - here's what our future overlords think of my answer:

The analysis appears to be accurate. The INT_TO_FIX and FIX_TO_INT macros are used for fixed-point arithmetic, and the maximum value that can be represented using these macros is limited by the number of bits used for the fixed-point representation. In the given code, the macros use 12 bits for the fractional part, which limits the maximum value that can be represented to 4096 (2^12). This means that sounds larger than 1 million bytes (just under 1 megabyte) will get truncated, leading to sounds being limited to around 10 seconds, depending on the quality settings.

The suggested workaround of dividing the long track into smaller files and using a daisy chain playback to seamlessly play the divided sounds as a single track is a valid solution to the issue. However, it requires a complex script to monitor and manage the playback of the individual sound files.


See, I'm bot approved. 😁

DC
 
Back
Top Bottom