/// <summary> /// (Private) Private method handling low-level OpenAL calls required to play a sound, used by PlaySound() and PlayLoopingSound(). /// </summary> /// <param name="channel">The sound channel in which to play the sound</param> /// <param name="file">The sound file, as it appears in the file sourced used by FileSystem</param> /// <param name="volume">Volume at which the sound should be played, 1.0 means normal, 0.5 means half volume, 2.0 means twice as loud</param> /// <param name="pitch">Pitch at which the sound should be played. 1.0 means normal, 0.5 means 2x slower, 2.0 means 2x faster.</param> /// <param name="looping">Should the sound be looping?</param> /// <returns>True if everything went well, false otherwise</returns> private bool PlaySoundInChannel(int channel, string file, float volume, float pitch, bool looping) { if (!Enabled) { return(false); } if ((channel < 0) || (channel >= TOTAL_CHANNELS)) { return(false); // Channel index is out of bounds } if (!PrecacheSound(file)) { return(false); // Failed to precache the sound (wrong data or file do not exist) } AudioPlayerSound sound = SoundCache[file]; StopSound(channel); SoundChannels[channel] = AL.GenSource(); AL.Source(SoundChannels[channel], ALSourcef.Gain, OneBitOfTools.Clamp(volume, 0f, 10f)); AL.Source(SoundChannels[channel], ALSourcef.Pitch, OneBitOfTools.Clamp(pitch, 0.01f, 10f)); AL.Source(SoundChannels[channel], ALSourcei.Buffer, sound.Buffer); AL.Source(SoundChannels[channel], ALSourceb.Looping, looping); AL.SourcePlay(SoundChannels[channel]); return(true); }
/// <summary> /// Loads a sound from the engine's FileSystem and plays it. /// If the sound wasn't precached, it will be automatically before it is played. /// Make sure the Enabled() method was called or no sound will be played. /// </summary> /// <param name="file">The name of the file, as found in the FileSystem file source</param> /// <param name="volume">Volume at which the sound should be played, 1.0 means normal, 0.5 means half volume, 2.0 means twice as loud</param> /// <param name="pitch">Pitch at which the sound should be played. 1.0 means normal, 0.5 means 2x slower, 2.0 means 2x faster.</param> /// <param name="randomPitch">Random pitch variation to add or subtract to the "base" pitch. (e.g. with pitch=1.0 and randomPitch=0.1, actual pitch will be between 0.9 and 1.1)</param> /// <returns>True if everything went correctly, false otherwise</returns> public bool PlaySound(string file, float volume = 1.0f, float pitch = 1.0f, float randomPitch = 0.0f) { if (!Enabled) { return(false); } int freeChannel = -1; for (int i = 0; i < SINGLE_CHANNELS; i++) // Look for an unused channel or a channel with a sound which is done playing { if ( (SoundChannels[i] == -1) || (AL.GetSourceState(SoundChannels[i]) != ALSourceState.Playing) ) { freeChannel = i; break; } } if (freeChannel == -1) { return(false); // No available channel } float realPitch = pitch + OneBitOfTools.RandomFloat(-randomPitch, randomPitch); PlaySoundInChannel(freeChannel, file, volume, realPitch, false); return(true); }
/// <summary> /// (Internal) Draws the control on the provided VBO. /// </summary> /// <param name="vbo">UI VBO on which to draw the control.</param> internal override void UpdateVBOTiles(VBO vbo) { string[] lines = OneBitOfTools.WordWrap(Text_, Width); if ((lines.Length >= Height) && (Width >= 4)) // Too many lines { lines[Height - 1] = lines[Height - 1].Substring(0, Math.Min(lines[Height - 1].Length, Width - 4)); lines[Height - 1] += "..."; } for (int i = 0; i < lines.Length; i++) { if (i >= Height) { break; } DrawTextOnVBO(vbo, lines[i], Position.X, Position.Y + i, FontTile_, Color, TileEffect); } }
/// <summary> /// Returns a copy of this position with X and Y coordinates clamped to the bounds of an area. /// </summary> /// <param name="area">The area in which the position must be contained</param> /// <returns>A copy of this position with X and Y coordinates clamped to the bounds of an area</returns> public Position Bound(Area area) { return(new Position( OneBitOfTools.Clamp(X, area.Left, area.Right - 1), OneBitOfTools.Clamp(Y, area.Top, area.Bottom - 1))); }
/// <summary> /// (Private) Makes sure an integer value is in the 0-255 range. /// </summary> /// <param name="value">An integer value</param> /// <returns>The value, bounded in the 0-255 range</returns> private static int BoundChannelValue(int value) { return(OneBitOfTools.Clamp(value, 0, 255)); }