menu.h \
mousecursor.cpp \
mousecursor.h \
-music_manager.cpp \
-music_manager.h \
musicref.cpp \
musicref.h \
particlesystem.cpp \
setup.h \
sound.cpp \
sound.h \
+sound_manager.h \
+sound_manager.cpp \
special.cpp \
special.h \
sprite.h \
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);
}
}
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());
}
}
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;
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;
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;
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);
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);
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
/* 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) {
#include "resources.h"
#include "background.h"
#include "tilemap.h"
-#include "music_manager.h"
GameSession* GameSession::current_ = 0;
void
GameSession::levelintro(void)
{
- music_manager->halt_music();
+ sound_manager->halt_music();
char str[60];
{
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.)
}
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): */
#include "tile.h"
#include "lispreader.h"
#include "resources.h"
-#include "music_manager.h"
#include "gameobjs.h"
#include "lispwriter.h"
#include "button.h"
#include "tile.h"
#include "resources.h"
-#include "music_manager.h"
#include "background.h"
// TODO
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;
+++ /dev/null
-// $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);
-}
-
+++ /dev/null
-// $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
-
{
}
-MusicRef::MusicRef(MusicManager::MusicResource* newmusic)
+MusicRef::MusicRef(SoundManager::MusicResource* newmusic)
: music(newmusic)
{
if(music)
MusicRef&
MusicRef::operator =(const MusicRef& other)
{
- MusicManager::MusicResource* oldres = music;
+ SoundManager::MusicResource* oldres = music;
music = other.music;
if(music)
music->refcount++;
#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.
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
}
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;
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);
+}
+
/** 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;
#include "tilemap.h"
#include "camera.h"
#include "gameobjs.h"
+#include "resources.h"
#include "interactive_object.h"
#include "screen/screen.h"
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;
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)
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]);
}
}
if(dying)
return;
- play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
+ sound_manager->play_sound(sounds[SND_HURT]);
physic.set_velocity_x(0);
#include "special.h"
#include "resources.h"
#include "sprite_manager.h"
+#include "sound_manager.h"
#include "setup.h"
Surface* img_waves[3];
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()
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");
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");
}
delete sprite_manager;
sprite_manager = 0;
- delete music_manager;
- music_manager = 0;
+ delete sound_manager;
+ sound_manager = 0;
}
/* EOF */
#include "musicref.h"
class SpriteManager;
-class MusicManager;
+class SoundManager;
extern Surface* img_waves[3];
extern Surface* img_water;
extern MusicRef level_end_song;
extern SpriteManager* sprite_manager;
-extern MusicManager* music_manager;
+extern SoundManager* sound_manager;
void loadshared();
void unloadshared();
#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"
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;
}
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;
(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;
{
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;
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!
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
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)
{
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);
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);
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;
}
}
#include "worldmap.h"
#include "resources.h"
#include "intro.h"
-#include "music_manager.h"
+#include "sound_manager.h"
#include "player.h"
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:
// 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"
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;
}
void close_audio( void )
{
if (audio_device) {
- Mix_UnregisterAllEffects( SOUND_LEFT_SPEAKER );
- Mix_UnregisterAllEffects( SOUND_RIGHT_SPEAKER );
Mix_CloseAudio();
}
}
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 );
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,
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*/
--- /dev/null
+// $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);
+}
+
--- /dev/null
+// $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
+
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)
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);
}
{
if(player_status.lives < MAX_LIVES) {
player_status.lives++;
- play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
+ sound_manager->play_sound(sounds[SND_LIFEUP]);
}
}
#include "setup.h"
#include "sector.h"
#include "worldmap.h"
+#include "sound_manager.h"
#include "resources.h"
namespace WorldMapNS {
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);
break;
}
- music_manager->play_music(song);
+ sound_manager->play_music(song);
Menu::set_current(0);
if (!savegame_file.empty())
savegame(savegame_file);
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;