Line 2,997: |
Line 2,997: |
| | | |
| ==Manage audio in C#== | | ==Manage audio in C#== |
− | ===Overview=== | + | ===Play sound effects=== |
− | Here is a reference chart for sound methods which you can use for various cases:
| + | The game mostly handles sound effects through the <samp>Game1.sounds</samp> field. This has low-level methods like <samp>PlayLocal</samp>, <samp>PlayAll</samp>, <samp>GetVolumeForDistance</samp>, etc. |
| + | |
| + | However, you should rarely call <samp>Game1.sounds</samp> directly. Instead the game has four main methods for playing a sound effect: |
| | | |
| {| class="wikitable" | | {| class="wikitable" |
− | |+ Singleplayer and multiplayer sound functions
| |
− | |-
| |
− | ! Singleplayer only name !! Multiplayer equivalent !! Use case
| |
− | |-
| |
− | | <samp>Game1.playSound</samp> || N/A || UI and menu sounds; playing a sound for one player only
| |
| |- | | |- |
− | | <samp>GameLocation.localSound</samp> || <samp>GameLocation.playSound</samp> || For any in-game interactions on specific maps only
| + | ! method |
| + | ! usage |
| |- | | |- |
− | | <samp>GameLocation.localSoundAt</samp> || <samp>GameLocation.playSoundAt</samp> || For playing spatial sounds in specific tiles or coordinates, which change volume and location based on player proximity | + | | <samp>Game1.playSound</samp> |
− | |-
| + | | Play a sound for the current player only, which isn't synced in multiplayer and isn't affected by location or distance. This is mainly used for UI and menu sounds. |
− | | <samp>Game1.playSoundPitched</samp> || <samp>GameLocation.playSoundPitched</samp> || For playing any sounds at a different pitch than the original sound
| |
− | |-
| |
− | | <samp>DelayedAction.playSoundAfterDelay</samp> || N/A || For playing sounds after a specific period of time has passed
| |
− | |}
| |
| | | |
− | ===Play client-side sounds===
| + | For example: |
− | <dt><samp>Game1.playSound</samp></dt>
| |
− | <dd>
| |
− | You can play a sound for the current player only, played from no specific location, by calling the <samp>Game1.playSound()</samp> method. For example:
| |
| <syntaxhighlight lang="c#"> | | <syntaxhighlight lang="c#"> |
− | // For UI elements, such as when the player crafts a new item. | + | // for UI elements (e.g. crafting an item) |
| Game1.playSound("crafting"); | | Game1.playSound("crafting"); |
| </syntaxhighlight> | | </syntaxhighlight> |
− | This is useful for playing sounds in user interfaces, such as menus, where you don't need to play the sound from any particular map or player location.
| + | |- |
− | </dd>
| + | | <samp>GameLocation.localSound</samp><br /><samp>GameLocation.playSound</samp> |
| + | | Play a sound for the current player (<samp>localSound</samp>) or all players (<samp>playSound</samp>) if they're in this location. |
| + | |
| + | You can optionally specify... |
| + | * a tile position (which attenuates volume for each player based on their distance from the sound's source); |
| + | * and/or pitch (from 0 to 2400 with intervals of 100 between every half step, where 1200 is the default pitch). |
| | | |
− | <dt><samp>GameLocation.localSound</samp></dt>
| + | For example: |
− | <dd>
| |
− | Similarly, you can play a sound for the current player only, played from a specific map, by calling the <samp>GameLocation.localSound()</samp> method:
| |
| <syntaxhighlight lang="c#"> | | <syntaxhighlight lang="c#"> |
− | // For playing sounds in specific maps, such as a shipping bin on a farm. | + | // play sound for the current player if they're anywhere on the farm |
− | if (this.shippingBinLid.pingPongMotion != 1 && Game1.currentLocation.Equals(this.farm))
| + | Game1.getFarm().localSound("doorCreak"); |
− | {
| |
− | this.farm.localSound("doorCreak");
| |
− | }
| |
− | </syntaxhighlight>
| |
− | You can use this to assure that a sound is being played and heard only from a specific map.
| |
− | </dd>
| |
| | | |
− | <dt><samp>GameLocation.localSoundAt</samp></dt>
| + | // play sound for the current player if they're on the farm near the mailbox (fading with distance) |
− | <dd>
| + | Farm farm = Game1.getFarm(); |
− | This works just like the <samp>localSound</samp> method, except that it plays spatial audio, and will adjust the played sound's volume and position based on its proximity from the player. Sounds played from <samp>GameLocation.localSoundAt()</samp> will not be heard if the provided position is off-screen.
| + | farm.localSound("doorCreak", farm.GetMainMailboxPosition()); |
− | <syntaxhighlight lang="c#">
| |
− | // You can use this method to play sounds
| |
− | // that are far from, or close to the player.
| |
− | // This is some of the code used for the running sounds, played while riding on a horse.
| |
− | public virtual void PerformDefaultHorseFootstep(string step_type)
| |
− | {
| |
− | // ...
| |
− | if (step_type == "Wood")
| |
− | {
| |
− | if (this.rider.ShouldHandleAnimationSound())
| |
− | {
| |
− | this.rider.currentLocation.localSoundAt("woodyStep", base.getTileLocation());
| |
− | }
| |
− | // ...
| |
− | </syntaxhighlight>
| |
− | </dd>
| |
| | | |
− | <dt><samp>Game1.playSoundPitched</samp></dt>
| + | // play sound for all players on the farm near the mailbox (fading with distance), with a -200 pitch shift |
− | <dd>
| + | Farm farm = Game1.getFarm(); |
− | If desired, you can pitch shift a sound at intervals of 100 per half step, with 1200 being the pitch of the original sample.
| + | farm.playSound("doorCreak", farm.GetMainMailboxPosition(), 1000); |
− | <br />
| |
− | To play a sound at a higher or lower pitch, for the current player only with no specific location, you can call the <samp>Game1.playSoundPitched()</samp> method:
| |
− | <syntaxhighlight lang="c#">
| |
− | // The singleplayer code for Elliott's piano,
| |
− | // located in his cabin.
| |
− | switch (key)
| |
− | {
| |
− | case 1:
| |
− | this.playSoundPitched("toyPiano", 1100);
| |
− | break;
| |
− | case 2:
| |
− | this.playSoundPitched("toyPiano", 1500);
| |
− | break;
| |
− | case 3:
| |
− | this.playSoundPitched("toyPiano", 1600);
| |
− | break;
| |
− | case 4:
| |
− | this.playSoundPitched("toyPiano", 1800);
| |
− | break;
| |
− | }
| |
| </syntaxhighlight> | | </syntaxhighlight> |
− | </dd> | + | |- |
| + | | <samp>DelayedAction.playSoundAfterDelay</samp> |
| + | | Play a sound for the current or all players after a specified delay in milliseconds. You can optionally specify a location, tile position, and pitch (which works the same way as the <samp>GameLocation</samp> methods). You can call this method repeatedly to play multiple sounds (e.g. for a sequence of sounds with different delays). |
| | | |
− | <dt><samp>DelayedAction.playSoundAfterDelay</samp></dt>
| + | For example: |
− | <dd>
| |
− | Sometimes, you need to play a sound after waiting a certain period of time, for the current player at no particular location. In this case, you can call the <samp>DelayedAction.playSoundAfterDelay()</samp> method:
| |
− | <syntaxhighlight lang="c#">
| |
− | // During a lightning storm, if the random chance is met,
| |
− | // the screen will flash, and then
| |
− | // a distant lightning strike sound will play after a
| |
− | // randomly generated duration of time in milliseconds
| |
− | if (Game1.random.NextDouble() < 0.5)
| |
− | DelayedAction.screenFlashAfterDelay((float) (0.3 + Game1.random.NextDouble()), Game1.random.Next(500, 1000));
| |
− | DelayedAction.playSoundAfterDelay("thunder_small", Game1.random.Next(500, 1500));
| |
− | // ...
| |
− | </syntaxhighlight>
| |
− | You can also change the sound's pitch with this function, or call this function several times at once to call them in a predetermined order:
| |
| <syntaxhighlight lang="c#"> | | <syntaxhighlight lang="c#"> |
− | // When using the phone that is purchasable from the Carpenter's Shop, | + | // play sound for the current player after 1.5 seconds, no matter where they are |
− | // it will play a specific sequence of dial beeps at predetermined times:
| + | DelayedAction.playSoundAfterDelay("thunder_small", 1500); |
− | private void playShopPhoneNumberSounds(string whichShop)
| |
− | {
| |
− | Random random = new Random(whichShop.GetHashCode());
| |
− | DelayedAction.playSoundAfterDelay("telephone_dialtone", 495, pitch: 1200);
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 1200, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 1370, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 1600, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 1850, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 2030, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 2250, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_buttonPush", 2410, pitch: (1200 + random.Next(-4, 5) * 100));
| |
− | DelayedAction.playSoundAfterDelay("telephone_ringingInEar", 3150);
| |
− | }
| |
− | </syntaxhighlight>
| |
− | </dd>
| |
| | | |
− | ===Play multiplayer sounds===
| + | // play sound for all players on the farm after 1.5 seconds, fading with distance from the mailbox |
− | The methods in this section will let you play sounds across different clients in a multiplayer game.
| + | Farm farm = Game1.getFarm(); |
− | <br />
| + | DelayedAction.playSoundAfterDelay("doorCreak", farm, farm.GetMainMailboxPosition()); |
− | Sounds played with multiplayer methods will run in singleplayer as well as multiplayer.
| |
| | | |
− | <dt><samp>GameLocation.playSound</samp></dt>
| + | // play sound for the current player only if they'rte on the farm after 1.5 seconds, fading with distance from the mailbox |
− | <dd>
| + | Farm farm = Game1.getFarm(); |
− | This method will play a sound for all players located on the same map, but not from a particular position:
| + | DelayedAction.playSoundAfterDelay("doorCreak", farm, farm.GetMainMailboxPosition(), local: true); |
− | <syntaxhighlight lang="c#">
| |
− | // When a player places a new structure, a sound will be played
| |
− | // for the players that are at the same location,
| |
− | // ie. on the farm.
| |
− | public virtual void performActionOnConstruction(GameLocation location)
| |
− | {
| |
− | this.load();
| |
− | location.playSound("axchop");
| |
− | // ...
| |
| </syntaxhighlight> | | </syntaxhighlight> |
− | </dd>
| + | |} |
| | | |
− | <dt><samp>GameLocation.playSoundAt</samp></dt>
| + | ===Add custom audio=== |
− | <dd>
| + | '''TODO: update for [[Modding:Migrate to Stardew Valley 1.6#Custom audio|custom audio in Stardew Valley 1.6]]''' |
− | Like <samp>localSoundAt</samp>, this method can be used to play sounds spatially at a specific map and location, and will adjust the played sound's volume and position based on its proximity from a nearby player. A player will not hear any sound played from the <samp>GameLocation.playSoundAt()</samp> method if the provided position is off-screen:
| |
− | <syntaxhighlight lang="c#">
| |
− | // The sound code for when Clint is metalworking in the Blacksmith.
| |
− | private void clintHammerSound(Farmer who)
| |
− | {
| |
− | base.currentLocation.playSoundAt("hammer", base.getTileLocation());
| |
− | }
| |
− | </syntaxhighlight>
| |
− | </dd>
| |
| | | |
− | <dt><samp>GameLocation.playSoundPitched</samp></dt>
| |
− | <dd>
| |
− | Like <samp>Game1.playSoundPitched</samp>, you can repitch sounds by providing a pitch from 0 to 2400, with intervals of 100 between every half step. However, with the <samp>GameLocation.playSoundPitched</samp> function, you must specify a map location to play the sound in, which any player in that location will hear.
| |
− | </dd>
| |
− |
| |
− | ===Add custom audio===
| |
| Game audio is split up into components: | | Game audio is split up into components: |
| *The SoundEffect is the object that stores the sound audio itself. | | *The SoundEffect is the object that stores the sound audio itself. |
Line 3,207: |
Line 3,108: |
| | | |
| ===Edit existing audio=== | | ===Edit existing audio=== |
| + | '''TODO: update for [[Modding:Migrate to Stardew Valley 1.6#Custom audio|custom audio in Stardew Valley 1.6]]''' |
| + | |
| To modify a cue that exists in the game, you can declare it from an existing cue as a new cue definition, and invoke <samp>CueDefinition.SetSound</samp> to apply your new audio to the cue. | | To modify a cue that exists in the game, you can declare it from an existing cue as a new cue definition, and invoke <samp>CueDefinition.SetSound</samp> to apply your new audio to the cue. |
| | | |