introduce a new SoundManager class and merged MusicManager with it. Using this class...
authorMatthias Braun <matze@braunis.de>
Mon, 31 May 2004 22:13:15 +0000 (22:13 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 31 May 2004 22:13:15 +0000 (22:13 +0000)
SVN-Revision: 1376

23 files changed:
src/Makefile.am
src/badguy.cpp
src/gameloop.cpp
src/level.cpp
src/leveleditor.cpp
src/moving_object.h
src/music_manager.cpp [deleted file]
src/music_manager.h [deleted file]
src/musicref.cpp
src/musicref.h
src/physic.cpp
src/physic.h
src/player.cpp
src/resources.cpp
src/resources.h
src/sector.cpp
src/setup.cpp
src/sound.cpp
src/sound.h
src/sound_manager.cpp [new file with mode: 0644]
src/sound_manager.h [new file with mode: 0644]
src/special.cpp
src/worldmap.cpp

index fb4eb3a..0f8302b 100644 (file)
@@ -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 \
index cfdc7ac..6b61c57 100644 (file)
@@ -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) {
index 08df481..613d927 100644 (file)
@@ -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): */
index cc30db4..bc6a69a 100644 (file)
@@ -36,7 +36,6 @@
 #include "tile.h"
 #include "lispreader.h"
 #include "resources.h"
-#include "music_manager.h"
 #include "gameobjs.h"
 #include "lispwriter.h"
 
index bb163d8..cb8f714 100644 (file)
@@ -43,7 +43,6 @@
 #include "button.h"
 #include "tile.h"
 #include "resources.h"
-#include "music_manager.h"
 #include "background.h"
 
 // TODO
index f4c93b6..988c752 100644 (file)
@@ -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 (file)
index 7cf9e9c..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
-//
-//  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 <assert.h>
-#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<std::string, MusicResource>::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<std::string, MusicResource>::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<std::map<std::string, MusicResource>::iterator, bool> result = 
-    musics.insert(
-        std::make_pair<std::string, MusicResource> (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 (file)
index 80706fd..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-//  Copyright (C) 2004 Duong-Khang NGUYEN <neoneurone@users.sf.net>
-//
-//  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 <SDL_mixer.h>
-#include <string>
-#include <map>
-
-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<std::string, MusicResource> musics;
-  MusicResource* current_music;
-  bool music_enabled;
-};
-
-#endif
-
index 3ba754b..55d0e67 100644 (file)
@@ -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++;
index baa0cd5..330601b 100644 (file)
@@ -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
index ef6d94c..7300b9e 100644 (file)
@@ -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);
+}
+
index 558cebd..002b42f 100644 (file)
@@ -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;
index f9a6032..655911d 100644 (file)
@@ -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);
 
index 62928e4..921e4d5 100644 (file)
@@ -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 */
index 18c3fb5..edff837 100644 (file)
@@ -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();
index 0976bb8..434582b 100644 (file)
@@ -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;
   }
 }
index 34891f2..055356b 100644 (file)
@@ -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:
index 6f4d82f..83c8bbb 100644 (file)
@@ -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 );
index d38b1ff..c2545a2 100644 (file)
@@ -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 (file)
index 0000000..c95902e
--- /dev/null
@@ -0,0 +1,189 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  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 "sound_manager.h"
+
+#include <math.h>
+#include <assert.h>
+#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<std::string, MusicResource>::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<std::string, MusicResource>::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<std::map<std::string, MusicResource>::iterator, bool> result = 
+    musics.insert(
+        std::make_pair<std::string, MusicResource> (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 (file)
index 0000000..d34082a
--- /dev/null
@@ -0,0 +1,71 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  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 __SOUND_MANAGER_H__
+#define __SOUND_MANAGER_H__
+
+#include "vector.h"
+#include <SDL_mixer.h>
+#include <string>
+#include <map>
+
+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<std::string, MusicResource> musics;
+  MusicResource* current_music;
+  bool music_enabled;
+};
+
+#endif
+
index 0c88288..1ff38f0 100644 (file)
@@ -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]);
           }
         }
 
index 3f529e0..5a52357 100644 (file)
@@ -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;