From: Matthias Braun Date: Mon, 31 May 2004 22:13:15 +0000 (+0000) Subject: introduce a new SoundManager class and merged MusicManager with it. Using this class... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=aea1b715f22599f5e202693cb93a0852704d6422;p=supertux.git introduce a new SoundManager class and merged MusicManager with it. Using this class we can create real stereo effects based on player position, without adding strange hacks to badguy.cpp SVN-Revision: 1376 --- diff --git a/src/Makefile.am b/src/Makefile.am index fb4eb3a24..0f8302b0c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,8 +46,6 @@ menu.cpp \ menu.h \ mousecursor.cpp \ mousecursor.h \ -music_manager.cpp \ -music_manager.h \ musicref.cpp \ musicref.h \ particlesystem.cpp \ @@ -62,6 +60,8 @@ setup.cpp \ setup.h \ sound.cpp \ sound.h \ +sound_manager.h \ +sound_manager.cpp \ special.cpp \ special.h \ sprite.h \ diff --git a/src/badguy.cpp b/src/badguy.cpp index cfdc7ac43..6b61c573c 100644 --- a/src/badguy.cpp +++ b/src/badguy.cpp @@ -356,7 +356,7 @@ BadGuy::action_mriceblock(double elapsed_time) tux.kick_timer.start(KICKING_TIME); set_sprite(img_mriceblock_flat_left, img_mriceblock_flat_right); physic.set_velocity_x((dir == LEFT) ? -3.5 : 3.5); - play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_KICK], this); } } @@ -366,15 +366,7 @@ BadGuy::action_mriceblock(double elapsed_time) check_horizontal_bump(); if(mode == KICK && changed != dir) { - float scroll_x = Sector::current()->camera->get_translation().x; - - /* handle stereo sound (number 10 should be tweaked...)*/ - if (base.x < scroll_x + screen->w/2 - 10) - play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER); - else if (base.x > scroll_x + screen->w/2 + 10) - play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER); - else - play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_RICOCHET], get_pos()); } } @@ -568,16 +560,7 @@ BadGuy::action_bomb(double elapsed_time) dying = DYING_NOT; // now the bomb hurts timer.start(EXPLODETIME); - float scroll_x = Sector::current()->camera->get_translation().x; - - /* play explosion sound */ // FIXME: is the stereo all right? maybe we should use player cordinates... - if (base.x < scroll_x + screen->w/2 - 10) - play_sound(sounds[SND_EXPLODE], SOUND_LEFT_SPEAKER); - else if (base.x > scroll_x + screen->w/2 + 10) - play_sound(sounds[SND_EXPLODE], SOUND_RIGHT_SPEAKER); - else - play_sound(sounds[SND_EXPLODE], SOUND_CENTER_SPEAKER); - + sound_manager->play_sound(sounds[SND_EXPLODE], this); } else if(mode == BOMB_EXPLODE) { remove_me(); return; @@ -1054,7 +1037,8 @@ BadGuy::squish_me(Player* player) Sector::current()->add_score(Vector(base.x, base.y), 50 * player_status.score_multiplier); - play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); + + sound_manager->play_sound(sounds[SND_SQUISH], get_pos()); player_status.score_multiplier++; dying = DYING_SQUISHED; @@ -1074,7 +1058,7 @@ BadGuy::squish(Player* player) make_player_jump(player); Sector::current()->add_score(Vector(base.x, base.y), 50 * player_status.score_multiplier); - play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_SQUISH], get_pos()); player_status.score_multiplier++; return; @@ -1082,7 +1066,7 @@ BadGuy::squish(Player* player) if (mode == NORMAL || mode == KICK) { /* Flatten! */ - play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_STOMP], get_pos()); mode = FLAT; set_sprite(img_mriceblock_flat_left, img_mriceblock_flat_right); physic.set_velocity_x(0); @@ -1090,7 +1074,7 @@ BadGuy::squish(Player* player) timer.start(4000); } else if (mode == FLAT) { /* Kick! */ - play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_KICK], this); if (player->base.x < base.x + (base.width/2)) { physic.set_velocity_x(5); @@ -1191,7 +1175,7 @@ BadGuy::kill_me(int score) score * player_status.score_multiplier); /* Play death sound: */ - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_FALL], this); } void @@ -1354,7 +1338,7 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type) /* Get kicked if were flat */ if (mode == FLAT && !dying) { - play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_KICK], this); // Hit from left side if (player->base.x < base.x) { diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 08df4819a..613d92764 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -55,7 +55,6 @@ #include "resources.h" #include "background.h" #include "tilemap.h" -#include "music_manager.h" GameSession* GameSession::current_ = 0; @@ -145,7 +144,7 @@ GameSession::~GameSession() void GameSession::levelintro(void) { - music_manager->halt_music(); + sound_manager->halt_music(); char str[60]; @@ -459,7 +458,7 @@ GameSession::check_end_conditions() { end_sequence = ENDSEQUENCE_RUNNING; last_x_pos = -1; - music_manager->play_music(level_end_song, 0); + sound_manager->play_music(level_end_song, 0); endsequence_timer.start(7000); // 5 seconds until we finish the map tux->invincible_timer.start(7000); //FIXME: Implement a winning timer for the end sequence (with special winning animation etc.) } @@ -689,7 +688,7 @@ void bumpbrick(float x, float y) Sector::current()->add_bouncy_brick(Vector(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32)); - play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_BRICK], Vector(x, y)); } /* (Status): */ diff --git a/src/level.cpp b/src/level.cpp index cc30db43f..bc6a69af4 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -36,7 +36,6 @@ #include "tile.h" #include "lispreader.h" #include "resources.h" -#include "music_manager.h" #include "gameobjs.h" #include "lispwriter.h" diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index bb163d8c0..cb8f714cd 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -43,7 +43,6 @@ #include "button.h" #include "tile.h" #include "resources.h" -#include "music_manager.h" #include "background.h" // TODO diff --git a/src/moving_object.h b/src/moving_object.h index f4c93b6d6..988c75238 100644 --- a/src/moving_object.h +++ b/src/moving_object.h @@ -39,6 +39,9 @@ public: virtual void collision(const MovingObject& other_object, int collision_type) = 0; + Vector get_pos() const + { return Vector(base.x, base.y); } + base_type base; base_type old_base; diff --git a/src/music_manager.cpp b/src/music_manager.cpp deleted file mode 100644 index 7cf9e9c79..000000000 --- a/src/music_manager.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2004 Ingo Ruhnke -// -// 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 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include "music_manager.h" -#include "musicref.h" -#include "sound.h" -#include "setup.h" - -MusicManager::MusicManager() - : current_music(0), music_enabled(true) -{ } - -MusicManager::~MusicManager() -{ - if(audio_device) - Mix_HaltMusic(); -} - -MusicRef -MusicManager::load_music(const std::string& file) -{ - if(!audio_device) - return MusicRef(0); - - if(!exists_music(file)) - st_abort("Couldn't load musicfile ", file.c_str()); - - std::map::iterator i = musics.find(file); - assert(i != musics.end()); - return MusicRef(& (i->second)); -} - -bool -MusicManager::exists_music(const std::string& file) -{ - if(!audio_device) - return true; - - // song already loaded? - std::map::iterator i = musics.find(file); - if(i != musics.end()) { - return true; - } - - Mix_Music* song = Mix_LoadMUS(file.c_str()); - if(song == 0) - return false; - - // insert into music list - std::pair::iterator, bool> result = - musics.insert( - std::make_pair (file, MusicResource())); - MusicResource& resource = result.first->second; - resource.manager = this; - resource.music = song; - - return true; -} - -void -MusicManager::free_music(MusicResource* ) -{ - // TODO free music, currently we can't do this since SDL_mixer seems to have - // some bugs if you load/free alot of mod files. -} - -void -MusicManager::play_music(const MusicRef& musicref, int loops) -{ - if(!audio_device) - return; - - if(musicref.music == 0 || current_music == musicref.music) - return; - - if(current_music) - current_music->refcount--; - - current_music = musicref.music; - current_music->refcount++; - - if(music_enabled) - Mix_PlayMusic(current_music->music, loops); -} - -void -MusicManager::halt_music() -{ - if(!audio_device) - return; - - Mix_HaltMusic(); - - if(current_music) { - current_music->refcount--; - if(current_music->refcount == 0) - free_music(current_music); - current_music = 0; - } -} - -void -MusicManager::enable_music(bool enable) -{ - if(!audio_device) - return; - - if(enable == music_enabled) - return; - - music_enabled = enable; - if(music_enabled == false) { - Mix_HaltMusic(); - } else { - Mix_PlayMusic(current_music->music, -1); - } -} - -MusicManager::MusicResource::~MusicResource() -{ - // buggy SDL_mixer :-/ - // Mix_FreeMusic(music); -} - diff --git a/src/music_manager.h b/src/music_manager.h deleted file mode 100644 index 80706fd05..000000000 --- a/src/music_manager.h +++ /dev/null @@ -1,66 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2000 Bill Kendrick -// Copyright (C) 2004 Duong-Khang NGUYEN -// -// 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 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef HEADER_MUSIC_MANAGER_H -#define HEADER_MUSIC_MANAGER_H - -#include -#include -#include - -class MusicRef; - -/** This class manages a list of music resources and is responsible for playing - * the music. - */ -class MusicManager -{ -public: - MusicManager(); - ~MusicManager(); - - MusicRef load_music(const std::string& file); - bool exists_music(const std::string& filename); - - void play_music(const MusicRef& music, int loops = -1); - void halt_music(); - - void enable_music(bool enable); - -private: - friend class MusicRef; - class MusicResource - { - public: - ~MusicResource(); - - MusicManager* manager; - Mix_Music* music; - int refcount; - }; - - void free_music(MusicResource* music); - - std::map musics; - MusicResource* current_music; - bool music_enabled; -}; - -#endif - diff --git a/src/musicref.cpp b/src/musicref.cpp index 3ba754bcc..55d0e6781 100644 --- a/src/musicref.cpp +++ b/src/musicref.cpp @@ -24,7 +24,7 @@ MusicRef::MusicRef() { } -MusicRef::MusicRef(MusicManager::MusicResource* newmusic) +MusicRef::MusicRef(SoundManager::MusicResource* newmusic) : music(newmusic) { if(music) @@ -50,7 +50,7 @@ MusicRef::MusicRef(const MusicRef& other) MusicRef& MusicRef::operator =(const MusicRef& other) { - MusicManager::MusicResource* oldres = music; + SoundManager::MusicResource* oldres = music; music = other.music; if(music) music->refcount++; diff --git a/src/musicref.h b/src/musicref.h index baa0cd583..330601ba6 100644 --- a/src/musicref.h +++ b/src/musicref.h @@ -19,7 +19,7 @@ #ifndef HEADER_MUSIC_RESOURCE_H #define HEADER_MUSIC_RESOURCE_H -#include "music_manager.h" +#include "sound_manager.h" /** This class holds a reference to a music file and maintains a correct * refcount for that file. @@ -34,10 +34,10 @@ public: MusicRef& operator= (const MusicRef& other); private: - friend class MusicManager; - MusicRef(MusicManager::MusicResource* music); + friend class SoundManager; + MusicRef(SoundManager::MusicResource* music); - MusicManager::MusicResource* music; + SoundManager::MusicResource* music; }; #endif diff --git a/src/physic.cpp b/src/physic.cpp index ef6d94c24..7300b9e3c 100644 --- a/src/physic.cpp +++ b/src/physic.cpp @@ -122,7 +122,7 @@ Physic::enable_gravity(bool enable_gravity) } void -Physic::apply(float frame_ratio, float &x, float &y) +Physic::apply(float elapsed_time, float &x, float &y) { float gravity = Sector::current()->gravity; float grav; @@ -131,8 +131,15 @@ Physic::apply(float frame_ratio, float &x, float &y) else grav = 0; - x += vx * frame_ratio + ax * frame_ratio * frame_ratio; - y += vy * frame_ratio + (ay + grav) * frame_ratio * frame_ratio; - vx += ax * frame_ratio; - vy += (ay + grav) * frame_ratio; + x += vx * elapsed_time + ax * elapsed_time * elapsed_time; + y += vy * elapsed_time + (ay + grav) * elapsed_time * elapsed_time; + vx += ax * elapsed_time; + vy += (ay + grav) * elapsed_time; } + +void +Physic::apply(Vector& vector, float elapsed_time) +{ + apply(elapsed_time, vector.x, vector.y); +} + diff --git a/src/physic.h b/src/physic.h index 558cebd4c..002b42f80 100644 --- a/src/physic.h +++ b/src/physic.h @@ -63,6 +63,9 @@ public: /** applies the physical simulation to given x and y coordinates */ void apply(float frame_ratio, float &x, float &y); + /** applies the physical simulation to given x and y coordinates */ + void apply(Vector& vector, float frame_ratio); + private: /// horizontal and vertical acceleration float ax, ay; diff --git a/src/player.cpp b/src/player.cpp index f9a6032fd..655911dd3 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -31,6 +31,7 @@ #include "tilemap.h" #include "camera.h" #include "gameobjs.h" +#include "resources.h" #include "interactive_object.h" #include "screen/screen.h" @@ -413,7 +414,7 @@ Player::handle_horizontal_input() if(on_ground() && ((vx < 0 && dirsign >0) || (vx>0 && dirsign<0))) { if(fabs(vx)>SKID_XM && !skidding_timer.check()) { skidding_timer.start(SKID_TIME); - play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_SKID]); ax *= 2.5; } else { ax *= 2; @@ -480,9 +481,9 @@ Player::handle_vertical_input() jumping = true; can_jump = false; if (size == SMALL) - play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_JUMP]); else - play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_BIGJUMP]); } // Let go of jump key else if(input.up == UP && jumping && physic.get_velocity_y() > 0) @@ -668,7 +669,7 @@ Player::grabdistros() if(player_status.lives < MAX_LIVES) ++player_status.lives; /*We want to hear the sound even, if MAX_LIVES is reached*/ - play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_LIFEUP]); } } @@ -906,7 +907,7 @@ Player::kill(HurtMode mode) if(dying) return; - play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_HURT]); physic.set_velocity_x(0); diff --git a/src/resources.cpp b/src/resources.cpp index 62928e497..921e4d50a 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -25,6 +25,7 @@ #include "special.h" #include "resources.h" #include "sprite_manager.h" +#include "sound_manager.h" #include "setup.h" Surface* img_waves[3]; @@ -39,7 +40,7 @@ MusicRef herring_song; MusicRef level_end_song; SpriteManager* sprite_manager = 0; -MusicManager* music_manager = 0; +SoundManager* sound_manager = 0; /* Load graphics/sounds shared between all levels: */ void loadshared() @@ -47,8 +48,8 @@ void loadshared() int i; sprite_manager = new SpriteManager(datadir + "/supertux.strf"); - music_manager = new MusicManager(); - music_manager->enable_music(use_music); + sound_manager = new SoundManager(); + sound_manager->enable_music(use_music); /* Tuxes: */ smalltux_star = sprite_manager->load("smalltux-star"); @@ -214,8 +215,8 @@ void loadshared() sounds[i] = load_sound(datadir + soundfilenames[i]); /* Herring song */ - herring_song = music_manager->load_music(datadir + "/music/SALCON.MOD"); - level_end_song = music_manager->load_music(datadir + "/music/tux-leveldone.mod"); + herring_song = sound_manager->load_music(datadir + "/music/SALCON.MOD"); + level_end_song = sound_manager->load_music(datadir + "/music/tux-leveldone.mod"); } @@ -251,8 +252,8 @@ void unloadshared(void) delete sprite_manager; sprite_manager = 0; - delete music_manager; - music_manager = 0; + delete sound_manager; + sound_manager = 0; } /* EOF */ diff --git a/src/resources.h b/src/resources.h index 18c3fb5d9..edff837ee 100644 --- a/src/resources.h +++ b/src/resources.h @@ -23,7 +23,7 @@ #include "musicref.h" class SpriteManager; -class MusicManager; +class SoundManager; extern Surface* img_waves[3]; extern Surface* img_water; @@ -38,7 +38,7 @@ extern MusicRef herring_song; extern MusicRef level_end_song; extern SpriteManager* sprite_manager; -extern MusicManager* music_manager; +extern SoundManager* sound_manager; void loadshared(); void unloadshared(); diff --git a/src/sector.cpp b/src/sector.cpp index 0976bb806..434582b0c 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -33,7 +33,7 @@ #include "particlesystem.h" #include "tile.h" #include "tilemap.h" -#include "music_manager.h" +#include "sound_manager.h" #include "gameloop.h" #include "resources.h" #include "interactive_object.h" @@ -608,7 +608,7 @@ Sector::add_bullet(const Vector& pos, float xm, Direction dir) throw std::runtime_error("wrong bullet type."); add_object(new_bullet); - play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_SHOOT]); return true; } @@ -643,7 +643,7 @@ Sector::trybreakbrick(const Vector& pos, bool small) solids->change_at(pos, tile->next_tile); } - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_DISTRO]); player_status.score = player_status.score + SCORE_DISTRO; player_status.distros++; return true; @@ -659,7 +659,7 @@ Sector::trybreakbrick(const Vector& pos, bool small) (int)(pos.y / 32) * 32), tile); /* Get some score: */ - play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_BRICK]); player_status.score = player_status.score + SCORE_BRICK; return true; @@ -689,7 +689,7 @@ Sector::tryemptybox(const Vector& pos, Direction col_side) { case 1: // Box with a distro! add_bouncy_distro(Vector(posx, posy)); - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_DISTRO]); player_status.score = player_status.score + SCORE_DISTRO; player_status.distros++; break; @@ -699,7 +699,7 @@ Sector::tryemptybox(const Vector& pos, Direction col_side) add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP); else /* Tux is big, add a fireflower: */ add_upgrade(Vector(posx, posy), col_side, UPGRADE_FIREFLOWER); - play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_UPGRADE]); break; case 5: // Add an ice flower upgrade! @@ -707,7 +707,7 @@ Sector::tryemptybox(const Vector& pos, Direction col_side) add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP); else /* Tux is big, add an iceflower: */ add_upgrade(Vector(posx, posy), col_side, UPGRADE_ICEFLOWER); - play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_UPGRADE]); break; case 3: // Add a golden herring @@ -734,7 +734,7 @@ Sector::trygrabdistro(const Vector& pos, int bounciness) return; solids->change_at(pos, tile->next_tile); - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_DISTRO]); if (bounciness == BOUNCE) { @@ -778,7 +778,7 @@ Sector::load_music() char* song_path; char* song_subtitle; - level_song = music_manager->load_music(datadir + "/music/" + song_title); + level_song = sound_manager->load_music(datadir + "/music/" + song_title); song_path = (char *) malloc(sizeof(char) * datadir.length() + strlen(song_title.c_str()) + 8 + 5); @@ -786,10 +786,10 @@ Sector::load_music() strcpy(strstr(song_subtitle, "."), "\0"); sprintf(song_path, "%s/music/%s-fast%s", datadir.c_str(), song_subtitle, strstr(song_title.c_str(), ".")); - if(!music_manager->exists_music(song_path)) { + if(!sound_manager->exists_music(song_path)) { level_song_fast = level_song; } else { - level_song_fast = music_manager->load_music(song_path); + level_song_fast = sound_manager->load_music(song_path); } free(song_subtitle); free(song_path); @@ -801,16 +801,16 @@ Sector::play_music(int type) currentmusic = type; switch(currentmusic) { case HURRYUP_MUSIC: - music_manager->play_music(level_song_fast); + sound_manager->play_music(level_song_fast); break; case LEVEL_MUSIC: - music_manager->play_music(level_song); + sound_manager->play_music(level_song); break; case HERRING_MUSIC: - music_manager->play_music(herring_song); + sound_manager->play_music(herring_song); break; default: - music_manager->halt_music(); + sound_manager->halt_music(); break; } } diff --git a/src/setup.cpp b/src/setup.cpp index 34891f281..055356bb3 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -51,7 +51,7 @@ #include "worldmap.h" #include "resources.h" #include "intro.h" -#include "music_manager.h" +#include "sound_manager.h" #include "player.h" @@ -558,7 +558,7 @@ void process_options_menu(void) if(use_music != options_menu->isToggled(MNID_MUSIC)) { use_music = !use_music; - music_manager->enable_music(use_music); + sound_manager->enable_music(use_music); } break; case MNID_SHOWFPS: diff --git a/src/sound.cpp b/src/sound.cpp index 6f4d82f48..83c8bbb42 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -17,7 +17,6 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - #include "defines.h" #include "globals.h" #include "sound.h" @@ -66,13 +65,6 @@ int open_audio (int frequency, Uint16 format, int channels, int chunksize) if (Mix_AllocateChannels(8) != 8) return -2; - /* reserve some channels and register panning effects */ - if (Mix_ReserveChannels(SOUND_RESERVED_CHANNELS) != SOUND_RESERVED_CHANNELS) - return -3; - - /* prepare the spanning effects */ - Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); - Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); return 0; } @@ -82,8 +74,6 @@ int open_audio (int frequency, Uint16 format, int channels, int chunksize) void close_audio( void ) { if (audio_device) { - Mix_UnregisterAllEffects( SOUND_LEFT_SPEAKER ); - Mix_UnregisterAllEffects( SOUND_RIGHT_SPEAKER ); Mix_CloseAudio(); } } @@ -104,31 +94,6 @@ Mix_Chunk* load_sound(const std::string& file) return(snd); } -/* --- PLAY A SOUND ON LEFT OR RIGHT OR CENTER SPEAKER --- */ - -void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker) -{ - /* this won't call the function if the user has disabled sound - * either via menu or via command-line option - */ - if(!audio_device || !use_sound) - return; - - Mix_PlayChannel( whichSpeaker, snd, 0); - - /* prepare for panning effects for next call */ - switch (whichSpeaker) { - case SOUND_LEFT_SPEAKER: - Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); - break; - case SOUND_RIGHT_SPEAKER: - Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); - break; - default: // keep the compiler happy - break; - } -} - void free_chunk(Mix_Chunk *chunk) { Mix_FreeChunk( chunk ); diff --git a/src/sound.h b/src/sound.h index d38b1ff5a..c2545a235 100644 --- a/src/sound.h +++ b/src/sound.h @@ -36,14 +36,6 @@ enum Music_Type { HERRING_MUSIC }; -/* panning effects: terrible :-) ! */ -enum Sound_Speaker { - SOUND_LEFT_SPEAKER = 0, - SOUND_RIGHT_SPEAKER = 1, - SOUND_RESERVED_CHANNELS = 2, // 2 channels reserved for left/right speaker - SOUND_CENTER_SPEAKER = -1 -}; - /* Sound files: */ enum { SND_JUMP, @@ -82,6 +74,5 @@ void close_audio( void ); Mix_Chunk * load_sound(const std::string& file); void free_chunk(Mix_Chunk*chunk); -void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker); #endif /*SUPERTUX_SOUND_H*/ diff --git a/src/sound_manager.cpp b/src/sound_manager.cpp new file mode 100644 index 000000000..c95902e17 --- /dev/null +++ b/src/sound_manager.cpp @@ -0,0 +1,189 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2004 Matthias Braun +#include +#include "musicref.h" +#include "setup.h" +#include "sector.h" +#include "camera.h" +#include "sound.h" +#include "globals.h" +#include "moving_object.h" + +SoundManager::SoundManager() + : current_music(0), music_enabled(true) +{ +} + +SoundManager::~SoundManager() +{ + if(audio_device) + Mix_HaltMusic(); +} + +void +SoundManager::play_sound(Mix_Chunk* sound) +{ + if(!audio_device || !use_sound) + return; + + Mix_PlayChannel(-1, sound, 0); +} + +void +SoundManager::play_sound(Mix_Chunk* sound, const MovingObject* object) +{ + // TODO keep track of the object later and move the sound along with the + // object. + play_sound(sound, object->get_pos()); +} + +void +SoundManager::play_sound(Mix_Chunk* sound, const Vector& pos) +{ + if(!audio_device || !use_sound) + return; + + // TODO make sure this formula is good + float distance + = Sector::current()->player->get_pos().x - pos.x; + int loud = int(255.0/float(screen->w*2) * fabsf(distance)); + if(loud > 255) + return; + + int chan = Mix_PlayChannel(-1, sound, 0); + if(chan < 0) + return; + Mix_SetDistance(chan, loud); + + // very bad way to do this... + if(distance > 100) + Mix_SetPanning(chan, 230, 24); + else if(distance < -100) + Mix_SetPanning(chan, 24, 230); +} + +MusicRef +SoundManager::load_music(const std::string& file) +{ + if(!audio_device) + return MusicRef(0); + + if(!exists_music(file)) + st_abort("Couldn't load musicfile ", file.c_str()); + + std::map::iterator i = musics.find(file); + assert(i != musics.end()); + return MusicRef(& (i->second)); +} + +bool +SoundManager::exists_music(const std::string& file) +{ + if(!audio_device) + return true; + + // song already loaded? + std::map::iterator i = musics.find(file); + if(i != musics.end()) { + return true; + } + + Mix_Music* song = Mix_LoadMUS(file.c_str()); + if(song == 0) + return false; + + // insert into music list + std::pair::iterator, bool> result = + musics.insert( + std::make_pair (file, MusicResource())); + MusicResource& resource = result.first->second; + resource.manager = this; + resource.music = song; + + return true; +} + +void +SoundManager::free_music(MusicResource* ) +{ + // TODO free music, currently we can't do this since SDL_mixer seems to have + // some bugs if you load/free alot of mod files. +} + +void +SoundManager::play_music(const MusicRef& musicref, int loops) +{ + if(!audio_device) + return; + + if(musicref.music == 0 || current_music == musicref.music) + return; + + if(current_music) + current_music->refcount--; + + current_music = musicref.music; + current_music->refcount++; + + if(music_enabled) + Mix_PlayMusic(current_music->music, loops); +} + +void +SoundManager::halt_music() +{ + if(!audio_device) + return; + + Mix_HaltMusic(); + + if(current_music) { + current_music->refcount--; + if(current_music->refcount == 0) + free_music(current_music); + current_music = 0; + } +} + +void +SoundManager::enable_music(bool enable) +{ + if(!audio_device) + return; + + if(enable == music_enabled) + return; + + music_enabled = enable; + if(music_enabled == false) { + Mix_HaltMusic(); + } else { + Mix_PlayMusic(current_music->music, -1); + } +} + +SoundManager::MusicResource::~MusicResource() +{ + // don't free music buggy SDL_Mixer crashs for some mod files + // Mix_FreeMusic(music); +} + diff --git a/src/sound_manager.h b/src/sound_manager.h new file mode 100644 index 000000000..d34082a73 --- /dev/null +++ b/src/sound_manager.h @@ -0,0 +1,71 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2004 Matthias Braun +#include +#include + +class MusicRef; +class MovingObject; + +/** This class handles all sounds that are played + */ +class SoundManager +{ +public: + SoundManager(); + ~SoundManager(); + + void play_sound(Mix_Chunk* sound); + void play_sound(Mix_Chunk* sound, const Vector& pos); + void play_sound(Mix_Chunk* sound, const MovingObject* object); + + MusicRef load_music(const std::string& file); + bool exists_music(const std::string& filename); + + void play_music(const MusicRef& music, int loops = -1); + void halt_music(); + + void enable_music(bool enable); + +private: + // music part + friend class MusicRef; + class MusicResource + { + public: + ~MusicResource(); + + SoundManager* manager; + Mix_Music* music; + int refcount; + }; + + void free_music(MusicResource* music); + + std::map musics; + MusicResource* current_music; + bool music_enabled; +}; + +#endif + diff --git a/src/special.cpp b/src/special.cpp index 0c8828846..1ff38f040 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -265,7 +265,7 @@ Upgrade::bump(Player* player) if(kind != UPGRADE_GROWUP) return; - play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_BUMP_UPGRADE], Vector(base.x, base.y)); // determine new direction if (player->base.x + player->base.width/2 > base.x + base.width/2) @@ -308,30 +308,30 @@ Upgrade::collision(void* p_c_object, int c_object, CollisionType type) if (kind == UPGRADE_GROWUP) { - play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_EXCELLENT]); pplayer->grow(true); } else if (kind == UPGRADE_FIREFLOWER) { - play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_COFFEE]); pplayer->grow(true); pplayer->got_power = pplayer->FIRE_POWER; } else if (kind == UPGRADE_ICEFLOWER) { - play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_COFFEE]); pplayer->grow(true); pplayer->got_power = pplayer->ICE_POWER; } else if (kind == UPGRADE_FIREFLOWER) { - play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_COFFEE]); pplayer->grow(true); pplayer->got_power = pplayer->FIRE_POWER; } else if (kind == UPGRADE_HERRING) { - play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_HERRING]); pplayer->invincible_timer.start(TUX_INVINCIBLE_TIME); Sector::current()->play_music(HERRING_MUSIC); } @@ -339,7 +339,7 @@ Upgrade::collision(void* p_c_object, int c_object, CollisionType type) { if(player_status.lives < MAX_LIVES) { player_status.lives++; - play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_LIFEUP]); } } diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 3f529e01c..5a523572f 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -31,6 +31,7 @@ #include "setup.h" #include "sector.h" #include "worldmap.h" +#include "sound_manager.h" #include "resources.h" namespace WorldMapNS { @@ -690,8 +691,8 @@ WorldMap::update(float delta) if (!level->extro_filename.empty()) { MusicRef theme = - music_manager->load_music(datadir + "/music/theme.mod"); - music_manager->play_music(theme); + sound_manager->load_music(datadir + "/music/theme.mod"); + sound_manager->play_music(theme); // Display final credits and go back to the main menu display_text_file(level->extro_filename, "/images/background/extro.jpg", SCROLL_SPEED_MESSAGE); @@ -745,7 +746,7 @@ WorldMap::update(float delta) break; } - music_manager->play_music(song); + sound_manager->play_music(song); Menu::set_current(0); if (!savegame_file.empty()) savegame(savegame_file); @@ -901,8 +902,8 @@ WorldMap::display() quit = false; - song = music_manager->load_music(datadir + "/music/" + music); - music_manager->play_music(song); + song = sound_manager->load_music(datadir + "/music/" + music); + sound_manager->play_music(song); unsigned int last_update_time; unsigned int update_time;