home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * random_sound.cpp - random sounds support
- *
- * Copyright (C) 2008 Florian Richter
- ***************************************************************************/
- /*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include "../audio/random_sound.h"
- #include "../core/game_core.h"
- #include "../core/camera.h"
- #include "../core/framerate.h"
- #include "../audio/audio.h"
- #include "../video/renderer.h"
- #include "../input/mouse.h"
- #include "../core/math/utilities.h"
- #include "../core/i18n.h"
-
- /* *** *** *** *** *** cRandom_Sound *** *** *** *** *** *** *** *** *** *** *** */
-
- cRandom_Sound :: cRandom_Sound( void )
- : cSprite()
- {
- // Set defaults
- cRandom_Sound::Init();
- }
-
- cRandom_Sound :: cRandom_Sound( CEGUI::XMLAttributes &attributes )
- : cSprite()
- {
- cRandom_Sound::Init();
- cRandom_Sound::Create_from_Stream( attributes );
- }
-
- cRandom_Sound :: ~cRandom_Sound( void )
- {
-
- }
-
- void cRandom_Sound :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
- {
- // filename
- Set_Filename( attributes.getValueAsString( "file" ).c_str() );
- // position
- Set_Pos( static_cast<float>(attributes.getValueAsInteger( "pos_x" )), static_cast<float>(attributes.getValueAsInteger( "pos_y" )), 1 );
- //
- Set_Continuous( attributes.getValueAsBool( "continuous", m_continuous ) );
- // delay
- Set_Delay_Min( attributes.getValueAsInteger( "delay_min", m_delay_min ) );
- Set_Delay_Max( attributes.getValueAsInteger( "delay_max", m_delay_max ) );
- // volume
- Set_Volume_Min( attributes.getValueAsFloat( "volume_min", m_volume_min ) );
- Set_Volume_Max( attributes.getValueAsFloat( "volume_max", m_volume_max ) );
- // volume reduction
- Set_Volume_Reduction_Begin( attributes.getValueAsFloat( "volume_reduction_begin", m_volume_reduction_begin ) );
- Set_Volume_Reduction_End( attributes.getValueAsFloat( "volume_reduction_end", m_volume_reduction_end ) );
- }
-
- void cRandom_Sound :: Save_to_Stream( ofstream &ofile )
- {
- ofile << "\t<sound>" << std::endl;
-
- // filename
- ofile << "\t\t<Property name=\"file\" value=\"" << m_filename.c_str() << "\" />" << std::endl;
- // position
- ofile << "\t\t<Property name=\"pos_x\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
- ofile << "\t\t<Property name=\"pos_y\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
- // continuous
- ofile << "\t\t<Property name=\"continuous\" value=\"" << m_continuous << "\" />" << std::endl;
- // delay
- ofile << "\t\t<Property name=\"delay_min\" value=\"" << m_delay_min << "\" />" << std::endl;
- ofile << "\t\t<Property name=\"delay_max\" value=\"" << m_delay_max << "\" />" << std::endl;
- // volume
- ofile << "\t\t<Property name=\"volume_min\" value=\"" << m_volume_min << "\" />" << std::endl;
- ofile << "\t\t<Property name=\"volume_max\" value=\"" << m_volume_max << "\" />" << std::endl;
- // volume reduction
- ofile << "\t\t<Property name=\"volume_reduction_begin\" value=\"" << m_volume_reduction_begin << "\" />" << std::endl;
- ofile << "\t\t<Property name=\"volume_reduction_end\" value=\"" << m_volume_reduction_end << "\" />" << std::endl;
-
- ofile << "\t</sound>" << std::endl;
- }
-
- void cRandom_Sound :: Init( void )
- {
- sprite_array = ARRAY_ACTIVE;
- type = TYPE_SOUND;
- massivetype = MASS_PASSIVE;
- editor_posz = 0.111f;
- player_range = 0;
- name = "Sound";
-
- rect.w = 10;
- rect.h = 10;
- col_rect.w = rect.w;
- col_rect.h = rect.h;
- start_rect.w = rect.w;
- start_rect.h = rect.h;
-
- // default values
- m_continuous = 0;
- m_delay_min = 1000;
- m_delay_max = 5000;
- m_volume_min = 90;
- m_volume_max = 100;
- m_volume_reduction_begin = 400;
- m_volume_reduction_end = 1000;
-
- m_distance_to_camera = 0;
- m_next_play_delay = 0;
- m_volume_update_counter = 0;
-
- m_editor_color_volume_reduction_begin = Color( 0.1f, 0.5f, 0.1f, 0.2f );
- m_editor_color_volume_reduction_end = Color( 0.2f, 0.4f, 0.1f, 0.2f );
- }
-
- cRandom_Sound *cRandom_Sound :: Copy( void )
- {
- cRandom_Sound *random_sound = new cRandom_Sound();
- random_sound->Set_Pos( startposx, startposy, 1 );
- random_sound->Set_Filename( m_filename.c_str() );
- random_sound->Set_Continuous( m_continuous );
- random_sound->Set_Delay_Min( m_delay_min );
- random_sound->Set_Delay_Max( m_delay_max );
- random_sound->Set_Volume_Min( m_volume_min );
- random_sound->Set_Volume_Max( m_volume_max );
- random_sound->Set_Volume_Reduction_Begin( m_volume_reduction_begin );
- random_sound->Set_Volume_Reduction_End( m_volume_reduction_end );
-
- return random_sound;
- }
-
- void cRandom_Sound :: Set_Filename( string str )
- {
- // stop playing sounds
- for( unsigned int i = 0; i < 100; i++ )
- {
- cAudio_Sound *sound = pAudio->Get_Playing_Sound( m_filename );
-
- if( !sound )
- {
- break;
- }
-
- sound->Stop();
- }
-
- m_filename = str;
- }
-
- string cRandom_Sound :: Get_Filename( void ) const
- {
- return m_filename;
- }
-
- void cRandom_Sound :: Set_Continuous( bool continuous )
- {
- m_continuous = continuous;
- }
-
- void cRandom_Sound :: Set_Delay_Min( unsigned int delay )
- {
- if( delay < 20 )
- {
- delay = 20;
- }
-
- m_delay_min = delay;
- }
-
- unsigned int cRandom_Sound :: Get_Delay_Min( void ) const
- {
- return m_delay_min;
- }
-
- void cRandom_Sound :: Set_Delay_Max( unsigned int delay )
- {
- if( delay < 20 )
- {
- delay = 20;
- }
- else if( delay < m_delay_min )
- {
- delay = m_delay_min;
- }
-
- m_delay_max = delay;
- }
-
- unsigned int cRandom_Sound :: Get_Delay_Max( void ) const
- {
- return m_delay_max;
- }
-
- void cRandom_Sound :: Set_Volume_Min( float volume )
- {
- if( volume < 0.1f )
- {
- volume = 0.1f;
- }
- else if( volume > m_volume_max )
- {
- volume = m_volume_max;
- }
- else if( volume > 100 )
- {
- volume = 100;
- }
-
- m_volume_min = volume;
- }
-
- float cRandom_Sound :: Get_Volume_Min( void ) const
- {
- return m_volume_min;
- }
-
- void cRandom_Sound :: Set_Volume_Max( float volume )
- {
- if( volume < 0.1f )
- {
- volume = 0.1f;
- }
- else if( volume < m_volume_min )
- {
- volume = m_volume_min;
- }
- else if( volume > 100 )
- {
- volume = 100;
- }
-
- m_volume_max = volume;
- }
-
- float cRandom_Sound :: Get_Volume_Max( void ) const
- {
- return m_volume_max;
- }
-
- void cRandom_Sound :: Set_Volume_Reduction_Begin( float distance )
- {
- if( distance < 1 )
- {
- distance = 1;
- }
- else if( distance > m_volume_reduction_end )
- {
- distance = m_volume_reduction_end;
- }
-
- m_volume_reduction_begin = distance;
- }
-
- float cRandom_Sound :: Get_Volume_Reduction_Begin( void ) const
- {
- return m_volume_reduction_begin;
- }
-
- void cRandom_Sound :: Set_Volume_Reduction_End( float distance )
- {
- if( distance < 1 )
- {
- distance = 1;
- }
- else if( distance < m_volume_reduction_begin )
- {
- distance = m_volume_reduction_begin;
- }
-
- m_volume_reduction_end = distance;
- }
-
- float cRandom_Sound :: Get_Volume_Reduction_End( void ) const
- {
- return m_volume_reduction_end;
- }
-
- float cRandom_Sound :: Get_Distance_Volume_Mod( void )
- {
- // if in volume reduction range
- if( m_distance_to_camera > m_volume_reduction_begin )
- {
- float distance = m_distance_to_camera - m_volume_reduction_begin;
- return ( 1.0f - distance / ( m_volume_reduction_end - m_volume_reduction_begin ) );
- }
-
- // no reduction
- return 1.0f;
- }
-
- void cRandom_Sound :: Update( void )
- {
- Update_Valid_Update();
-
- if( !valid_update )
- {
- return;
- }
-
- bool play = 0;
-
- if( m_continuous )
- {
- m_volume_update_counter -= ( pFramerate->speedfactor * 1000 ) / static_cast<float>(speedfactor_fps);
-
- // get the sound
- cAudio_Sound *sound = pAudio->Get_Playing_Sound( m_filename );
-
- // if not playing
- if( !sound )
- {
- // play it
- play = 1;
- }
- // update volume
- else if( m_volume_update_counter <= 0 )
- {
- // volume based on maximum
- float sound_volume = m_volume_max * 0.01f;
- // apply distance modifier
- sound_volume *= Get_Distance_Volume_Mod();
- // set to mixer volume
- sound_volume *= static_cast<float>(MIX_MAX_VOLUME);
- // set volume
- pAudio->Set_Sound_Volume( static_cast<int>(sound_volume), sound->m_channel );
-
- // update volume every 100 ms
- m_volume_update_counter = 100;
- }
- }
- else
- {
- // subtract duration of this frame in milliseconds
- m_next_play_delay -= ( pFramerate->speedfactor * 1000 ) / static_cast<float>(speedfactor_fps);
-
- // play it
- if( m_next_play_delay <= 0 )
- {
- play = 1;
-
- // set next delay
- m_next_play_delay = static_cast<float>(m_delay_min);
-
- if( m_delay_max > m_delay_min )
- {
- m_next_play_delay += Get_Random_Float( 0, static_cast<float>(m_delay_max - m_delay_min) );
- }
- }
- }
-
- if( play )
- {
- float sound_volume = 0;
-
- // always maximum volume
- if( m_continuous )
- {
- sound_volume = m_volume_max;
- }
- // set random volume
- else
- {
- // random
- if( m_volume_max > m_volume_min )
- {
- sound_volume = Get_Random_Float( m_volume_min, m_volume_max );
- }
- // static
- else
- {
- sound_volume = m_volume_max;
- }
- }
-
- sound_volume *= 0.01f;
-
- // adjust volume based on distance
- sound_volume *= Get_Distance_Volume_Mod();
-
- int loops = 0;
-
- if( m_continuous )
- {
- // unlimited
- loops = -1;
- }
-
- sound_volume *= static_cast<float>(MIX_MAX_VOLUME);
-
- // play sound
- pAudio->Play_Sound( m_filename, -1, static_cast<int>(sound_volume), loops );
- }
- }
-
- void cRandom_Sound :: Draw( cSurfaceRequest *request /* = NULL */ )
- {
- if( !valid_draw )
- {
- return;
- }
-
- // draw color rect
- pVideo->Draw_Rect( col_rect.x - pActive_Camera->x, col_rect.y - pActive_Camera->y, col_rect.w, col_rect.h, editor_posz, &greenyellow );
- // volume reduction begin
- cCircleRequest *circle_request = new cCircleRequest();
- pVideo->Draw_Circle( col_rect.x - pActive_Camera->x, col_rect.y - pActive_Camera->y, m_volume_reduction_begin, editor_posz - 0.0001f, &m_editor_color_volume_reduction_begin, circle_request );
- circle_request->line_width = 3;
- // add request
- pRenderer->Add( circle_request );
- // volume reduction end
- circle_request = new cCircleRequest();
- pVideo->Draw_Circle( col_rect.x - pActive_Camera->x, col_rect.y - pActive_Camera->y, m_volume_reduction_end, editor_posz - 0.0002f, &m_editor_color_volume_reduction_end, circle_request );
- circle_request->line_width = 3;
- // add request
- pRenderer->Add( circle_request );
- }
-
- bool cRandom_Sound :: Is_Update_Valid( void )
- {
- // if destroyed
- if( destroy )
- {
- return 0;
- }
-
- // get distance from camera center position
- float dx = fabs( pActive_Camera->x + (game_res_w * 0.5f) - posx );
- float dy = fabs( pActive_Camera->y + (game_res_h * 0.5f) - posy );
-
- m_distance_to_camera = sqrt( dx * dx + dy * dy );
-
- // if outside the range
- if( m_distance_to_camera >= m_volume_reduction_end )
- {
- Event_Out_Of_Range();
- return 0;
- }
-
- return 1;
- }
-
- bool cRandom_Sound :: Is_Draw_Valid( void )
- {
- // if editor not enabled
- if( !editor_enabled )
- {
- return 0;
- }
-
- // if not visible on the screen or not mouse object
- if( !visible || ( !Is_Visible_on_Screen() && pMouseCursor->active_object != this ) )
- {
- return 0;
- }
-
- return 1;
- }
-
- void cRandom_Sound :: Event_Out_Of_Range( void )
- {
- // fade out sounds if out of range
- pAudio->Fadeout_Sounds( 500, m_filename );
- }
-
- void cRandom_Sound :: Editor_Activate( void )
- {
- CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
-
- // filename
- CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_filename" ));
- Editor_Add( UTF8_("Filename"), UTF8_("Sound filename"), editbox, 200 );
-
- editbox->setText( m_filename.c_str() );
- editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Filename_Key, this ) );
-
- // continuous
- CEGUI::Checkbox *checkbox = static_cast<CEGUI::Checkbox *>(wmgr.createWindow( "TaharezLook/Checkbox", "editor_sound_continuous" ));
- Editor_Add( UTF8_("Continuous"), UTF8_("Check if the sound should be played continuously instead of randomly"), checkbox, 50 );
-
- checkbox->setSelected( m_continuous );
- checkbox->subscribeEvent( CEGUI::Checkbox::EventCheckStateChanged, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Continuous_Changed, this ) );
-
- // delay min
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_delay_min" ));
- Editor_Add( UTF8_("Delay Minimum"), UTF8_("Minimal delay until played again"), editbox, 90 );
-
- editbox->setText( int_to_string( m_delay_min ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Delay_Min_Key, this ) );
-
- // delay max
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_delay_max" ));
- Editor_Add( UTF8_("Maximum"), UTF8_("Maximal delay until played again"), editbox, 90, 28, 0 );
-
- editbox->setText( int_to_string( m_delay_max ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Delay_Max_Key, this ) );
-
- // volume min
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_volume_min" ));
- Editor_Add( UTF8_("Volume Minimum"), UTF8_("Minimal random volume for each play"), editbox, 90 );
-
- editbox->setText( int_to_string( static_cast<int>(m_volume_min) ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Volume_Min_Key, this ) );
-
- // volume max
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_volume_max" ));
- Editor_Add( UTF8_("Maximum"), UTF8_("Maximal random volume for each play"), editbox, 90, 28, 0 );
-
- editbox->setText( int_to_string( static_cast<int>(m_volume_max) ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Volume_Max_Key, this ) );
-
- // volume reduction begin
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_volume_reduction_begin" ));
- Editor_Add( UTF8_("Volume Reduction Begin"), UTF8_("Volume reduction begins gradually at this distance"), editbox, 90 );
-
- editbox->setText( int_to_string( static_cast<int>(m_volume_reduction_begin) ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Volume_Reduction_Begin_Key, this ) );
-
- // volume reduction end
- editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_sound_volume_reduction_end" ));
- Editor_Add( UTF8_("End"), UTF8_("Volume reduction ends at this distance. Sound is not played beyond this."), editbox, 90, 28, 0 );
-
- editbox->setText( int_to_string( static_cast<int>(m_volume_reduction_end) ) );
- editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRandom_Sound::Editor_Volume_Reduction_End_Key, this ) );
-
- // init
- Editor_Init();
- }
-
- bool cRandom_Sound :: Editor_Filename_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Filename( str_text );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Continuous_Changed( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- bool enabled = static_cast<CEGUI::Checkbox *>( windowEventArgs.window )->isSelected();
-
- Set_Continuous( enabled );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Delay_Min_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Delay_Min( string_to_int( str_text ) );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Delay_Max_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Delay_Max( string_to_int( str_text ) );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Volume_Min_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Volume_Min( string_to_float( str_text ) );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Volume_Max_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Volume_Max( string_to_float( str_text ) );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Volume_Reduction_Begin_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Volume_Reduction_Begin( string_to_float( str_text ) );
-
- return 1;
- }
-
- bool cRandom_Sound :: Editor_Volume_Reduction_End_Key( const CEGUI::EventArgs &event )
- {
- const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
- string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
-
- Set_Volume_Reduction_End( string_to_float( str_text ) );
-
- return 1;
- }
-