14_SoundEffects.lua 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. -- Sound effects example
  2. -- This sample demonstrates:
  3. -- - Playing sound effects and music
  4. -- - Controlling sound and music master volume
  5. require "LuaScripts/Utilities/Sample"
  6. local soundNames = {
  7. "Fist",
  8. "Explosion",
  9. "Power-up"
  10. }
  11. local soundResourceNames = {
  12. "Sounds/PlayerFistHit.wav",
  13. "Sounds/BigExplosion.wav",
  14. "Sounds/Powerup.wav"
  15. }
  16. function Start()
  17. -- Execute the common startup for samples
  18. SampleStart()
  19. -- Enable OS cursor
  20. input.mouseVisible = true
  21. -- Create the user interface
  22. CreateUI()
  23. end
  24. function CreateUI()
  25. -- Create a scene which will not be actually rendered, but is used to hold SoundSource components while they play sounds
  26. scene_ = Scene()
  27. local uiStyle = cache:GetResource("XMLFile", "UI/DefaultStyle.xml")
  28. -- Set style to the UI root so that elements will inherit it
  29. ui.root.defaultStyle = uiStyle
  30. -- Create buttons for playing back sounds
  31. for i, v in ipairs(soundNames) do
  32. local button = CreateButton((i - 1) * 140 + 20, 20, 120, 40, v)
  33. -- Store the sound effect resource name as a custom variable into the button
  34. button:SetVar(StringHash("SoundResource"), Variant(soundResourceNames[i]))
  35. SubscribeToEvent(button, "Pressed", "HandlePlaySound")
  36. end
  37. -- Create buttons for playing/stopping music
  38. local button = CreateButton(20, 80, 120, 40, "Play Music")
  39. SubscribeToEvent(button, "Released", "HandlePlayMusic")
  40. button = CreateButton(160, 80, 120, 40, "Stop Music")
  41. SubscribeToEvent(button, "Released", "HandleStopMusic")
  42. -- Create sliders for controlling sound and music master volume
  43. local slider = CreateSlider(20, 140, 200, 20, "Sound Volume")
  44. slider.value = audio:GetMasterGain(SOUND_EFFECT)
  45. SubscribeToEvent(slider, "SliderChanged", "HandleSoundVolume")
  46. slider = CreateSlider(20, 200, 200, 20, "Music Volume")
  47. slider.value = audio:GetMasterGain(SOUND_MUSIC)
  48. SubscribeToEvent(slider, "SliderChanged", "HandleMusicVolume")
  49. end
  50. function CreateButton(x, y, xSize, ySize, text)
  51. local font = cache:GetResource("Font", "Fonts/Anonymous Pro.ttf")
  52. -- Create the button and center the text onto it
  53. local button = ui.root:CreateChild("Button")
  54. button:SetStyleAuto()
  55. button:SetPosition(x, y)
  56. button:SetSize(xSize, ySize)
  57. local buttonText = button:CreateChild("Text")
  58. buttonText:SetAlignment(HA_CENTER, VA_CENTER)
  59. buttonText:SetFont(font, 12)
  60. buttonText:SetText(text)
  61. return button
  62. end
  63. function CreateSlider(x, y, xSize, ySize, text)
  64. local font = cache:GetResource("Font", "Fonts/Anonymous Pro.ttf")
  65. -- Create text and slider below it
  66. local sliderText = ui.root:CreateChild("Text")
  67. sliderText:SetPosition(x, y)
  68. sliderText:SetFont(font, 12)
  69. sliderText:SetText(text)
  70. local slider = ui.root:CreateChild("Slider")
  71. slider:SetStyleAuto()
  72. slider:SetPosition(x, y + 20)
  73. slider:SetSize(xSize, ySize)
  74. -- Use 0-1 range for controlling sound/music master volume
  75. slider.range = 1.0
  76. return slider
  77. end
  78. function HandlePlaySound(sender, eventType, eventData)
  79. local button = tolua.cast(GetEventSender(), "Button")
  80. local soundResourceName = button:GetVar(StringHash("SoundResource")):GetString()
  81. -- Get the sound resource
  82. local sound = cache:GetResource("Sound", soundResourceName)
  83. if sound ~= nil then
  84. -- Create a scene node with a SoundSource component for playing the sound. The SoundSource component plays
  85. -- non-positional audio, so its 3D position in the scene does not matter. For positional sounds the
  86. -- SoundSource3D component would be used instead
  87. local soundNode = scene_:CreateChild("Sound")
  88. local soundSource = soundNode:CreateComponent("SoundSource")
  89. soundSource:Play(sound)
  90. -- In case we also play music, set the sound volume below maximum so that we don't clip the output
  91. soundSource.gain = 0.7
  92. -- Subscribe to the "sound finished" event generated by the SoundSource for removing the node once the sound has played
  93. -- Note: the event is sent through the Node (similar to e.g. node physics collision and animation trigger events)
  94. -- to not require subscribing to the particular component
  95. SubscribeToEvent(soundNode, "SoundFinished", "HandleSoundFinished");
  96. end
  97. end
  98. function HandlePlayMusic(eventType, eventData)
  99. -- Check if the music player node/component already exist
  100. if scene_:GetChild("Music") ~= nil then
  101. return
  102. end
  103. local music = cache:GetResource("Sound", "Music/Ninja Gods.ogg")
  104. -- Set the song to loop
  105. music.looped = true
  106. -- Create a scene node and a sound source for the music
  107. local musicNode = scene_:CreateChild("Music")
  108. local musicSource = musicNode:CreateComponent("SoundSource")
  109. -- Set the sound type to music so that master volume control works correctly
  110. musicSource.soundType = SOUND_MUSIC
  111. musicSource:Play(music)
  112. end
  113. function HandleStopMusic(eventType, eventData)
  114. -- Remove the music player node from the scene
  115. scene_:RemoveChild(scene_:GetChild("Music"))
  116. end
  117. function HandleSoundVolume(eventType, eventData)
  118. local newVolume = eventData["Value"]:GetFloat()
  119. audio:SetMasterGain(SOUND_EFFECT, newVolume)
  120. end
  121. function HandleMusicVolume(eventType, eventData)
  122. local newVolume = eventData["Value"]:GetFloat()
  123. audio:SetMasterGain(SOUND_MUSIC, newVolume)
  124. end
  125. function HandleSoundFinished(eventType, eventData)
  126. local soundNode = eventData["Node"]:GetPtr("Node")
  127. soundNode:Remove()
  128. end
  129. -- Create XML patch instructions for screen joystick layout specific to this sample app
  130. function GetScreenJoystickPatchString()
  131. return
  132. "<patch>" ..
  133. " <add sel=\"/element/element[./attribute[@name='Name' and @value='Button2']]\">" ..
  134. " <attribute name=\"Is Visible\" value=\"false\" />" ..
  135. " </add>" ..
  136. " <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">" ..
  137. " <attribute name=\"Is Visible\" value=\"false\" />" ..
  138. " </add>" ..
  139. "</patch>"
  140. end