--------------------------- --------------------------- -- 3D Sound example -- Copyright (c) 2007-09 Capricorn 76 Pty. Ltd. -- -- ScriptENGINE supports 2D/3D sound. -- Sounds can be loaded and played as background music or sound fx. -- Sounds can be streamed from disk (for large files) or loaded entirely in memory (for smaller, frequently used fx). -- Sounds can be attached to 3D entities, and automatically moved around the scene with the entity. -- -- NOTE: -- The ./Demos/runDemo.e76script is a utility script used to run all the examples. -- It loads the world, calls the OnWorldLoad(), OnWorldUnload() functions, and runs the graphics engine loop, waiting for the user to press escape. --------------------------- --------------------------- local subTick = nil; local subGui = nil; local moveCube = false; local cubeAngle = 0; local cubeRadius = 0; --------------------------- -- runDemo.e76script calls this function when the world is loaded --------------------------- function OnWorldLoad(worldName) --print('OnWorldLoad'); --------------------------- -- The SDK world editor creates a worldIds.e76script when the world is saved. It contains all the entity ids. -- We load the IDs so that we can refer to the world entities using friendly names. --------------------------- IApp:loadScript(IWorld:getNameLong() .. '/worldIds'); -- Load this example's GUI OnWorldLoadGui(); -- Precalculate how big the cube's circle path will be based upon its starting position cubeRadius = IMisc:vectorGetLength(IWorld:getEntityPosition(idUnit_box)); --------------------------- -- Subscribe to the graphics engine 'tick' event. -- Our callback will be periodically fired by the graphics engine, -- so we can do some extra processing. -- -- Could create a thread to manage this, -- but we're showing how this can be done from the graphics engine thread. -- -- Note that you should do minimal processing this way, -- because the graphics can become jerky as the processing load increases. -- -- The returned identifier is later used to unsubscribe. --------------------------- subTick = IEvents:subscribeTickPeriodic('OnGraphicsTick', 100); subGui = IEvents:subscribeGui('OnGui'); --------------------------- -- Play some music and attach it to Agent. -- If he moves, the sound will follow. -- The engine will search its filesystem for the matching file. -- NB: 3D sounds must have only one channel (ie. mono) --------------------------- ISound:load('agentMusic', './Resource/music3d.ogg', false); if (ISound:soundExists('agentMusic')) then print('Loaded sound. Setting properties...'); -- Set the 3D position of the sound. -- Attached the sound to Agent ISound:setMaxDistance('agentMusic', 1000); ISound:setReferenceDistance('agentMusic', 10); ISound:setLooping('agentMusic', true); ISound:setVolume('agentMusic', 0.5); ISound:attachEntitySound(idAgent_Mech, 'agentMusic'); ISound:play('agentMusic'); end --------------------------- -- Attach a 3D sound to cube. -- Change the default minimum/maximum distances for the cube's 3D sounds. -- These control how close/far a sound can be heard from at max/min volume, depending on the sound engine's distance model. -- NB: 3D sounds must have only one channel (ie. mono) --------------------------- if (not(ISound:soundExists('sfx'))) then ISound:load('sfx', './Resource/sfx3d.wav', false); end if (ISound:soundExists('sfx')) then ISound:setMaxDistance('sfx', 1000); ISound:setReferenceDistance('sfx', 5); ISound:setVolume('sfx', 0.5); ISound:setLooping('sfx', true); ISound:attachEntitySound(idUnit_box, 'sfx'); ISound:play('sfx'); end --------------------------- -- Turn on auto camera movement. -- The active camera is 'fps' type, so it responds to mouse/key input in a first person shooter style --------------------------- IWorld:setActiveCameraAutoProcessed(true); end --------------------------- -- Load this example's GUI --------------------------- function OnWorldLoadGui() --------------------------- -- Let's show some help text --------------------------- IGraphics:loadGui('help'); end --------------------------- -- runDemo.e76script calls this function when the world is unloaded --------------------------- function OnWorldUnload(worldName) --print('OnWorldUnload'); --------------------------- -- Unsubscribe to events -- We will no longer be informed of the events. --------------------------- IEvents:unsubscribe(subTick); IEvents:unsubscribe(subGui); --------------------------- -- Stop sounds --------------------------- ISound:unload('agentMusic'); ISound:unload('sfx'); end ------------------------ -- Graphics tick event callback function. -- The graphics engine will periodically call this function based upon our subscription settings. -- We rotate the cube about the world's centre a little bit each time this callback is fired. ------------------------ function OnGraphicsTick(currentTime, lastTime, isWindowActive, userData) IWorld:manipulateEntity(idUnit_box, 'rotate', 0, 1, 1); if (moveCube) then cubeAngle = math.mod(cubeAngle + 2, 360); --print('cubeAngle:', cubeAngle); ------------------------ -- Calculate the cube's x/y/z position based upon -- our current angle and radius. We are basically -- rotating the cube in a circle around the world's center. ------------------------ X = math.cos(math.rad(cubeAngle)) * cubeRadius; Y = 0; -- The vertical dimension. Z = math.sin(math.rad(cubeAngle)) * cubeRadius; IWorld:setEntityPosition(idUnit_box, IMisc:vectorCreate(X, 0, Z)); end IWorld:manipulateEntity(idAgent_Mech, 'rotate', 0, 1, 0); end ------------------------ -- Gui handler ------------------------ function OnGui(callerId, eventType, userData) ----------------------- -- Change bell pitch ----------------------- if (IGraphics:scrollBarChanged('scrollBellPitch', callerId, eventType)) then -- Scale scrollbar value to between -1 and 1, then we take the exponential to make the pitch scale more user-friendly local pitch = math.exp((IGraphics:getScrollBarPos('scrollBellPitch') - 5) / 5); print('Changing bell pitch:', pitch); ISound:setPitch('sfx', pitch); -- 1 is the default, scale is logorithmic, so (2 = an octave up) and (0.5 = an octave down) ----------------------- -- Make directional sound ----------------------- elseif (IGraphics:checkboxClicked('checkboxDirectional', callerId, eventType)) then local enable = IGraphics:getCheckbox('checkboxDirectional'); if (enable) then -- The volume will be reduced outside the outer angle -- The sound's position and direction is updated with the entity it's attached to (ie. the box) ISound:setDirectionConeAngleParams('agentMusic', 90, 180, 0); ISound:setDirection('agentMusic', '1 0 0'); print('Enabling directional sound...'); else ISound:setDirectionConeAngleParams('agentMusic', 360, 360, 1); print('Disabling directional sound...'); end ----------------------- -- Move cube? ----------------------- elseif (IGraphics:checkboxClicked('checkboxMoveCube', callerId, eventType)) then moveCube = IGraphics:getCheckbox('checkboxMoveCube'); end end
Copyright © 2006-23 Sep 2009 Capricorn 76 Pty. Ltd. (created on Wed Sep 23 16:49:12 2009)