way.
OpenAL gives you some neat effects like positional sounds moving along while
they are played. Try a level with a flame to see this in action.
Some notes:
- don't forget to run autogen.sh and configure again
- The AmbientSound object probably needs an overhaul now
- You can't play .mod files anymore, they have to be converted to .ogg
- There's a bug that keeps supertux open for several seconds instead of closing
it, didn't investigate yet why.
SVN-Revision: 2636
fi
AC_SUBST([VARIANT])
+AC_C_BIGENDIAN()
+
AC_MSG_CHECKING(whether OpenGL should be used)
AC_ARG_ENABLE(opengl,
AC_HELP_STRING([--disable-opengl], [disable OpenGL support]),
:,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))
-NP_FINDLIB([SDLMIXER], [SDL_mixer], [SDL_mixer >= 1.2],
- NP_LANG_PROGRAM([#include <SDL_mixer.h>
-#if MIX_MAJOR_VERSION < 1
-# error SDLMix too old
-#else
-# if MIX_MAJOR_VERSION == 1
-# if MIX_MINOR_VERSION < 2
-# error SDLMix too old
-# endif
-# endif
-#endif], [Mix_OpenAudio(0, 0, 0, 0);]),
- [], [-lSDL_mixer],
- [],
- [AC_MSG_ERROR([Please install SDLMixer >=1.2.2])],
- [$SDL_CFLAGS], [$SDL_LIBS])
+XIPH_PATH_VORBIS(, [AC_MSG_ERROR([Please install libvorbis])])
+XIPH_PATH_OGG(, [AC_MSG_ERROR([Please install libogg])])
NP_FINDLIB([SDLIMAGE], [SDL_image], [SDL_image >= 1.2],
NP_LANG_PROGRAM([#include <SDL_image.h>], [IMG_Load("");]),
[],
[AC_MSG_ERROR([Please install physfs >= 1.0])])
+NP_FINDLIB([OPENAL], [OpenAL], [OpenAL],
+ NP_LANG_PROGRAM([#include <AL/alut.h>],
+ [alutInit(0, 0);]),
+ [], [-lopenal],
+ [],
+ [AC_MSG_ERROR([Please intall OpenAL])],
+ [], [])
+
dnl Checks for library functions.
AC_CHECK_FUNCS(mkdir strdup strstr)
(powerup (x 3168) (y 416)
(sprite (_ "eat-me"))
(script "
-function wait(time) {
- set_wakeup_time(time);
- suspend();
-}
DisplayEffect.fade_out(1);
wait(1);
Level.flip_vertically();
(powerup
(sprite "red-potion")
(script "
-function wait(time) {
- set_wakeup_time(time);
- suspend();
-}
DisplayEffect.fade_out(1);
wait(1);
Level.flip_vertically();
(powerup (x 8608) (y 1024)
(sprite "red-potion")
(script "
-function wait(time) {
- set_wakeup_time(time);
- suspend();
-}
DisplayEffect.fade_out(1);
wait(1);
Level.flip_vertically();
(powerup (x 9952) (y 416)
(sprite "red-potion")
(script "
-function wait(time) {
- set_wakeup_time(time);
- suspend();
-}
DisplayEffect.fade_out(1);
wait(1);
Level.flip_vertically();
)
(powerup (x 8000) (y 352)
(sprite "gold-key")
- (script "function wait(time) {
- set_wakeup_time(time);
- suspend();}
- wait(7);
+ (script "wait(7);
Level.finish();")
)
(infoblock (x 2560) (y 320)
sources =
[ Wildcard *.cpp *.h ]
[ Wildcard audio : *.cpp *.h ]
+ [ Wildcard audio/newapi : *.cpp *.h ]
[ Wildcard badguy : *.cpp *.h ]
[ Wildcard control : *.cpp *.h ]
[ Wildcard gui : *.cpp *.h ]
Application supertux : $(sources) $(wrapper_objects) ;
C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
LinkWith supertux : squirrel ;
-ExternalLibs supertux : SDL SDLMIXER SDLIMAGE GL ICONV PHYSFS BINRELOC ;
+ExternalLibs supertux : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
Help supertux : "Build the supertux executable" ;
IncludeDir supertux : squirrel/include ;
(semanticdb-project-database "semantic.cache"
:file "semantic.cache"
:tables (list
+ (semanticdb-table "sound_manager.cpp"
+ :file "sound_manager.cpp"
+ :pointmax 5898
+ :major-mode 'c++-mode
+ :tokens '(("sound_manager.h" include nil nil nil [1 27]) ("stdexcept" include t nil nil [29 49]) ("iostream" include t nil nil [50 69]) ("sstream" include t nil nil [70 88]) ("memory" include t nil nil [89 106]) ("sound_file.h" include nil nil nil [108 131]) ("sound_source.h" include nil nil nil [132 157]) ("stream_sound_source.h" include nil nil nil [158 190]) ("SoundManager" function ("SoundManager" type "class") nil ((parent . "SoundManager") (constructor . t)) nil nil [192 925]) ("SoundManager" function "void" nil ((parent . "SoundManager") (destructor . t)) nil nil [927 1366]) ("load_file_into_buffer" function ("ALuint" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [1411 1439])) ((parent . "SoundManager")) nil nil [1368 2032]) ("create_sound_source" function ("SoundSource" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [2081 2109])) ((parent . "SoundManager") (pointer . 1)) nil nil [2034 2556]) ("play" function ("void") (("soundname" variable ("std::string" type "class") nil ((const . t)) nil nil [2582 2611]) ("pos" variable ("Vector" type "class") nil ((const . t)) nil nil [2612 2630])) ((parent . "SoundManager")) nil nil [2558 3122]) ("enable_sound" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [3156 3168])) ((parent . "SoundManager")) nil nil [3124 3228]) ("enable_music" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [3262 3274])) ((parent . "SoundManager")) nil nil [3230 3363]) ("play_music" function ("void") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [3395 3423])) ((parent . "SoundManager")) nil nil [3365 3746]) ("set_listener_position" function ("void") (("pos" variable ("Vector" type "class") nil nil nil nil [3789 3800])) ((parent . "SoundManager")) nil nil [3748 3850]) ("set_listener_velocity" function ("void") (("vel" variable ("Vector" type "class") nil nil nil nil [3893 3904])) ((parent . "SoundManager")) nil nil [3852 3954]) ("update" function ("void") nil ((parent . "SoundManager")) nil nil [3956 4410]) ("get_sample_format" function ("ALenum" type "class") (("file" variable ("SoundFile" type "class") nil ((pointer . 1)) nil nil [4451 4467])) ((parent . "SoundManager")) nil nil [4412 5081]) ("print_openal_version" function ("void") nil ((parent . "SoundManager")) nil nil [5083 5410]) ("check_alc_error" function ("void") (("message" variable "char" nil ((const . t) (pointer . 1)) nil nil [5447 5467])) ((parent . "SoundManager")) nil nil [5412 5669]) ("check_al_error" function ("void") (("message" variable "char" nil ((const . t) (pointer . 1)) nil nil [5705 5725])) ((parent . "SoundManager")) nil nil [5671 5896]))
+ :unmatched-syntax 'nil
+ )
+ (semanticdb-table "stream_sound_source.h"
+ :file "stream_sound_source.h"
+ :pointmax 682
+ :major-mode 'c++-mode
+ :tokens '(("__STREAM_SOUND_SOURCE_H__" variable nil nil ((const . t)) nil nil [35 71]) ("sound_source.h" include nil nil nil [89 114]) ("SoundFile" type "class" nil nil nil nil nil [116 132]) ("StreamSoundSource" type "class" (("public" label ((reparse-symbol . classsubparts)) [181 188]) ("StreamSoundSource" function ("StreamSoundSource" type "class") (("file" variable ("SoundFile" type "class") nil ((pointer . 1)) nil nil [209 225])) ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [191 226]) ("StreamSoundSource" function "void" nil ((typemodifiers "virtual") (destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [229 258]) ("update" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [262 276]) ("private" label ((reparse-symbol . classsubparts)) [280 288]) ("STREAMFRAGMENTS" variable ("size_t" type "class") "5" ((const . t) (typemodifiers "static")) nil nil [344 384]) ("STREAMFRAGMENTS" variable "int" nil nil nil nil [452 468]) ("fillBufferAndQueue" function ("void") (("buffer" variable ("ALuint" type "class") nil nil nil nil [496 510])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [472 511]) ("file" variable ("SoundFile" type "class") nil ((pointer . 1)) nil nil [514 530]) ("buffers" variable ("ALuint" type "class") nil ((dereference . 1)) nil nil [533 565]) ("format" variable ("ALenum" type "class") nil nil nil nil [568 582]) ("FadeState" type "enum" (("NoFading" variable "int" nil ((const . t)) nil ((reparse-symbol . enumsubparts)) [603 612]) ("FadingOn" variable "int" nil ((const . t)) nil ((reparse-symbol . enumsubparts)) [613 622]) ("FadingOff" variable "int" nil ((const . t)) nil ((reparse-symbol . enumsubparts)) [623 634])) nil nil nil ((reparse-symbol . classsubparts)) [586 635]) ("fade_state" variable ("FadeState" type "class") nil nil nil nil [638 659])) (("SoundSource")) nil nil nil [134 672]))
+ )
(semanticdb-table "sound_manager.h"
:file "sound_manager.h"
- :pointmax 3413
+ :pointmax 1796
:major-mode 'c++-mode
- :tokens '(("SUPERTUX_SOUND_MANAGER_H" variable nil nil ((const . t)) nil nil [915 950]) ("string" include t nil nil [949 966]) ("vector" include t nil nil [967 984]) ("map" include t nil nil [985 999]) ("SDL_mixer.h" include nil nil nil [1001 1023]) ("math/vector.h" include nil nil nil [1024 1048]) ("MusicRef" type "class" nil nil nil nil nil [1077 1092]) ("MovingObject" type "class" nil nil nil nil nil [1093 1112]) ("SoundManager" type "class" (("public" label ((reparse-symbol . classsubparts)) [1206 1213]) ("SoundManager" function ("SoundManager" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1216 1231]) ("SoundManager" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1234 1250]) ("play_sound" function ("void") (("sound" variable ("std::string" type "class") nil ((const . t)) nil nil [1288 1313])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1272 1314]) ("play_sound" function ("void") (("sound" variable ("std::string" type "class") nil ((const . t)) nil nil [1375 1400]) ("pos" variable ("Vector" type "class") nil ((const . t)) nil nil [1401 1419]) ("pos2" variable ("Vector" type "class") nil ((const . t)) nil nil [1426 1445])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1359 1446]) ("play_sound" function ("void") (("sound" variable ("std::string" type "class") nil ((const . t)) nil nil [1523 1548]) ("object" variable ("MovingObject" type "class") nil ((const . t) (pointer . 1)) nil nil [1549 1576]) ("pos" variable ("Vector" type "class") nil ((const . t)) nil nil [1583 1601])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1507 1602]) ("load_music" function ("MusicRef" type "class") (("file" variable ("std::string" type "class") nil ((const . t)) nil nil [1699 1723])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1679 1724]) ("preload_sound" function ("Mix_Chunk" type "class") (("name" variable ("std::string" type "class") nil ((const . t)) nil nil [1934 1958])) ((pointer . 1) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1909 1959]) ("exists_music" function ("bool" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [2024 2052])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [2006 2053]) ("play_music" function ("void") (("music" variable ("MusicRef" type "class") nil ((const . t)) nil nil [2159 2181]) ("loops" variable "int" "-1" nil nil nil [2182 2196])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [2143 2198]) ("halt_music" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [2220 2238]) ("enable_music" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [2288 2300])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [2270 2301]) ("music_enabled" function ("bool" type "class") nil nil nil ((reparse-symbol . classsubparts)) [2329 2385]) ("enable_sound" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [2435 2447])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [2417 2448]) ("sound_enabled" function ("bool" type "class") nil nil nil ((reparse-symbol . classsubparts)) [2476 2532]) ("audio_device_available" function ("bool" type "class") nil nil nil ((reparse-symbol . classsubparts)) [2562 2624]) ("set_audio_device_available" function ("void") (("available" variable ("bool" type "class") nil nil nil nil [2660 2675])) nil nil ((reparse-symbol . classsubparts)) [2628 2713]) ("private" label ((reparse-symbol . classsubparts)) [2715 2723]) ("MusicRef" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [2733 2748]) ("Setup" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [2758 2770]) ("MusicResource" type "class" (("public" label ((reparse-symbol . classsubparts)) [2927 2934]) ("MusicResource" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [2941 2958]) ("manager" variable ("SoundManager" type "class") nil ((pointer . 1)) nil nil [2966 2988]) ("music" variable ("Mix_Music" type "class") nil ((pointer . 1)) nil nil [2995 3012]) ("refcount" variable "int" nil nil nil nil [3019 3032])) nil nil nil ((reparse-symbol . classsubparts)) [2897 3039]) ("free_music" function ("void") (("music" variable ("MusicResource" type "class") nil ((pointer . 1)) nil nil [3059 3080])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [3043 3081]) ("Sounds" type "typedef" nil ("std::map") ((typedef "std::map" type "class")) nil nil [3085 3134]) ("sounds" variable ("Sounds" type "class") nil nil nil nil [3137 3151]) ("Musics" type "typedef" nil ("std::map") ((typedef "std::map" type "class")) nil nil [3155 3207]) ("musics" variable ("Musics" type "class") nil nil nil nil [3210 3224]) ("current_music" variable ("MusicResource" type "class") nil ((pointer . 1)) nil nil [3228 3257]) ("m_music_enabled" variable ("bool" type "class") nil nil nil nil [3260 3281]) ("m_sound_enabled" variable ("bool" type "class") nil nil nil nil [3284 3305]) ("audio_device" variable ("bool" type "class") nil nil nil nil [3308 3326])) nil nil nil nil [1185 3374]))
- :unmatched-syntax 'nil
+ :tokens '(("__SOUND_MANAGER_H__" variable nil nil ((const . t)) nil nil [29 59]) ("math/vector.h" include nil nil nil [58 82]) ("string" include t nil nil [83 100]) ("vector" include t nil nil [101 118]) ("map" include t nil nil [119 133]) ("AL/alc.h" include t nil nil [135 154]) ("AL/al.h" include t nil nil [155 173]) ("SoundHandle" type "typedef" nil ("void") ((pointer . 1) (typedef "void")) nil nil [175 201]) ("SoundFile" type "class" nil nil nil nil nil [203 219]) ("SoundSource" type "class" nil nil nil nil nil [220 238]) ("StreamSoundSource" type "class" nil nil nil nil nil [239 263]) ("SoundManager" type "class" (("public" label ((reparse-symbol . classsubparts)) [286 293]) ("SoundManager" function ("SoundManager" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [296 311]) ("SoundManager" function "void" nil ((typemodifiers "virtual") (destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [314 338]) ("enable_sound" function ("void") (("sound_enabled" variable ("bool" type "class") nil nil nil nil [360 379])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [342 380]) ("create_sound_source" function ("SoundSource" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [692 720])) ((pointer . 1) (prototype . t)) nil ((reparse-symbol . classsubparts)) [659 721]) ("play" function ("void") (("name" variable ("std::string" type "class") nil ((const . t)) nil nil [890 914]) ("pos" variable ("Vector" type "class") "Vector(-1, -1)" ((const . t)) nil nil [915 949])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [880 951]) ("set_listener_position" function ("void") (("position" variable ("Vector" type "class") nil nil nil nil [982 998])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [955 999]) ("set_listener_velocity" function ("void") (("velocity" variable ("Vector" type "class") nil nil nil nil [1029 1045])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1002 1046]) ("enable_music" function ("void") (("music_enabled" variable ("bool" type "class") nil nil nil nil [1068 1087])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1050 1088]) ("play_music" function ("void") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [1107 1135])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1091 1136]) ("update" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1140 1154]) ("private" label ((reparse-symbol . classsubparts)) [1156 1164]) ("SoundSource" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [1174 1192]) ("StreamSoundSource" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [1202 1226]) ("load_file_into_buffer" function ("ALuint" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [1266 1294])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [1230 1295]) ("get_sample_format" function ("ALenum" type "class") (("file" variable ("SoundFile" type "class") nil ((pointer . 1)) nil nil [1330 1346])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [1298 1347]) ("print_openal_version" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1351 1379]) ("check_alc_error" function ("void") (("message" variable "char" nil ((const . t) (pointer . 1)) nil nil [1403 1423])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1382 1424]) ("check_al_error" function ("void") (("message" variable "char" nil ((const . t) (pointer . 1)) nil nil [1454 1474])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [1427 1475]) ("device" variable ("ALCdevice" type "class") nil ((pointer . 1)) nil nil [1479 1497]) ("context" variable ("ALCcontext" type "class") nil ((pointer . 1)) nil nil [1500 1520]) ("sound_enabled" variable ("bool" type "class") nil nil nil nil [1523 1542]) ("SoundBuffers" type "typedef" nil ("std::map") ((typedef "std::map" type "class")) nil nil [1546 1597]) ("buffers" variable ("SoundBuffers" type "class") nil nil nil nil [1600 1621]) ("SoundSources" type "typedef" nil ("std::vector") ((typedef "std::vector" type "class")) nil nil [1624 1671]) ("sources" variable ("SoundSources" type "class") nil nil nil nil [1674 1695]) ("music_source" variable ("StreamSoundSource" type "class") nil ((pointer . 1)) nil nil [1699 1731]) ("music_enabled" variable ("bool" type "class") nil nil nil nil [1735 1754]) ("current_music" variable ("std::string" type "class") nil nil nil nil [1757 1783])) nil nil nil nil [265 1786]))
+ :unmatched-syntax '((FRIEND 1195 . 1201) (FRIEND 1167 . 1173))
)
- (semanticdb-table "musicref.h"
- :file "musicref.h"
- :pointmax 1371
+ (semanticdb-table "stream_sound_source.cpp"
+ :file "stream_sound_source.cpp"
+ :pointmax 1971
:major-mode 'c++-mode
- :tokens '(("SUPERTUX_MUSICREF_H" variable nil nil ((const . t)) nil nil [907 937]) ("sound_manager.h" include nil nil nil [936 962]) ("SuperTux" type "namespace" (("MusicRef" type "class" (("public" label ((reparse-symbol . classsubparts)) [1085 1092]) ("MusicRef" function ("MusicRef" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1093 1106]) ("MusicRef" function ("MusicRef" type "class") (("other" variable ("MusicRef" type "class") nil ((const . t)) nil nil [1118 1140])) ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1107 1141]) ("MusicRef" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1142 1156]) ("=" function ("MusicRef" type "class") (("other" variable ("MusicRef" type "class") nil ((const . t)) nil nil [1183 1205])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [1160 1206]) ("private" label ((reparse-symbol . classsubparts)) [1208 1216]) ("SoundManager" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [1226 1245]) ("MusicRef" function ("MusicRef" type "class") (("music" variable ("SoundManager::MusicResource" type "class") nil ((pointer . 1)) nil nil [1257 1292])) ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [1246 1293]) ("music" variable ("SoundManager::MusicResource" type "class") nil ((pointer . 1)) nil nil [1297 1334])) nil nil nil ((reparse-symbol . namespacesubparts)) [1068 1337])) nil nil nil nil [964 1338]))
+ :tokens '(("config.h" include t nil nil [1 20]) ("stream_sound_source.h" include nil nil nil [22 54]) ("sound_manager.h" include nil nil nil [55 81]) ("sound_file.h" include nil nil nil [82 105]) ("StreamSoundSource" function ("StreamSoundSource" type "class") (("file" variable ("SoundFile" type "class") nil ((pointer . 1)) nil nil [144 160])) ((parent . "StreamSoundSource") (constructor . t)) nil nil [107 516]) ("StreamSoundSource" function "void" nil ((parent . "StreamSoundSource") (destructor . t)) nil nil [518 673]) ("update" function ("void") nil ((parent . "StreamSoundSource")) nil nil [675 1326]) ("fillBufferAndQueue" function ("void") (("buffer" variable ("ALuint" type "class") nil nil nil nil [1371 1385])) ((parent . "StreamSoundSource")) nil nil [1328 1970]))
)
- (semanticdb-table "sound_manager.cpp"
- :file "sound_manager.cpp"
- :pointmax 5703
+ (semanticdb-table "sound_source.h"
+ :file "sound_source.h"
+ :pointmax 474
+ :major-mode 'c++-mode
+ :tokens '(("__SOUND_SOURCE_H__" variable nil nil ((const . t)) nil nil [28 57]) ("AL/al.h" include t nil nil [56 74]) ("math/vector.h" include nil nil nil [75 99]) ("SoundSource" type "class" (("public" label ((reparse-symbol . classsubparts)) [121 128]) ("SoundSource" function ("SoundSource" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [131 145]) ("SoundSource" function "void" nil ((typemodifiers "virtual") (destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [148 171]) ("play" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [175 187]) ("stop" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [190 202]) ("playing" function ("bool" type "class") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [205 220]) ("set_looping" function ("void") (("looping" variable ("bool" type "class") nil nil nil nil [241 254])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [224 255]) ("set_volume" function ("void") (("volume" variable "float" nil nil nil nil [310 323])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [294 324]) ("set_position" function ("void") (("position" variable ("Vector" type "class") nil nil nil nil [345 361])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [327 362]) ("set_velocity" function ("void") (("position" variable ("Vector" type "class") nil nil nil nil [383 399])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [365 400]) ("protected" label ((reparse-symbol . classsubparts)) [402 412]) ("SoundManager" type "class" nil nil nil nil ((reparse-symbol . classsubparts)) [422 441]) ("source" variable ("ALuint" type "class") nil nil nil nil [447 461])) nil nil nil nil [101 464]))
+ )
+ (semanticdb-table "sound_file.cpp"
+ :file "sound_file.cpp"
+ :pointmax 7443
:major-mode 'c++-mode
- :tokens '(("config.h" include t nil nil [882 901]) ("cmath" include t nil nil [903 919]) ("cassert" include t nil nil [920 938]) ("sstream" include t nil nil [960 978]) ("audio/sound_manager.h" include nil nil nil [980 1012]) ("audio/musicref.h" include nil nil nil [1013 1040]) ("app/globals.h" include nil nil nil [1041 1065]) ("app/setup.h" include nil nil nil [1066 1088]) ("moving_object.h" include nil nil nil [1089 1115]) ("resources.h" include nil nil nil [1116 1138]) ("SoundManager" function ("SoundManager" type "class") nil ((parent . "SoundManager") (constructor . t)) nil nil [1167 1292]) ("SoundManager" function "void" nil ((parent . "SoundManager") (destructor . t)) nil nil [1294 1448]) ("play_sound" function ("void") (("name" variable ("std::string" type "class") nil ((const . t)) nil nil [1480 1504])) ((parent . "SoundManager")) nil nil [1450 1731]) ("play_sound" function ("void") (("sound" variable ("std::string" type "class") nil ((const . t)) nil nil [1763 1788]) ("object" variable ("MovingObject" type "class") nil ((const . t) (pointer . 1)) nil nil [1789 1816]) ("pos" variable ("Vector" type "class") nil ((const . t)) nil nil [1821 1839])) ((parent . "SoundManager")) nil nil [1733 1976]) ("play_sound" function ("void") (("sound" variable ("std::string" type "class") nil ((const . t)) nil nil [2008 2033]) ("pos" variable ("Vector" type "class") nil ((const . t)) nil nil [2034 2052]) ("pos2" variable ("Vector" type "class") nil ((const . t)) nil nil [2057 2076])) ((parent . "SoundManager")) nil nil [1978 2777]) ("load_music" function ("MusicRef" type "class") (("file" variable ("std::string" type "class") nil ((const . t)) nil nil [2813 2837])) ((parent . "SoundManager")) nil nil [2779 3197]) ("exists_music" function ("bool" type "class") (("file" variable ("std::string" type "class") nil ((const . t)) nil nil [3231 3255])) ((parent . "SoundManager")) nil nil [3199 3885]) ("free_music" function ("void") (("" variable ("MusicResource" type "class") nil ((pointer . 1)) nil nil [3917 3933])) ((parent . "SoundManager")) nil nil [3887 4069]) ("play_music" function ("void") (("musicref" variable ("MusicRef" type "class") nil ((const . t)) nil nil [4101 4126]) ("loops" variable "int" nil nil nil nil [4127 4137])) ((parent . "SoundManager")) nil nil [4071 4438]) ("halt_music" function ("void") nil ((parent . "SoundManager")) nil nil [4440 4682]) ("enable_music" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [4716 4728])) ((parent . "SoundManager")) nil nil [4684 4978]) ("enable_sound" function ("void") (("enable" variable ("bool" type "class") nil nil nil nil [5012 5024])) ((parent . "SoundManager")) nil nil [4980 5091]) ("MusicResource" function "void" nil ((parent . "SoundManager::MusicResource") (destructor . t)) nil nil [5093 5233]) ("preload_sound" function ("Mix_Chunk" type "class") (("name" variable ("std::string" type "class") nil ((const . t)) nil nil [5274 5298])) ((parent . "SoundManager") (pointer . 1)) nil nil [5235 5701]))
+ :tokens '(("config.h" include t nil nil [53 72]) ("sound_file.h" include nil nil nil [74 97]) ("stdio.h" include t nil nil [99 117]) ("stdint.h" include t nil nil [118 137]) ("algorithm" include t nil nil [138 158]) ("stdexcept" include t nil nil [159 179]) ("sstream" include t nil nil [180 198]) ("physfs.h" include t nil nil [199 218]) ("vorbis/codec.h" include t nil nil [219 244]) ("vorbis/vorbisfile.h" include t nil nil [245 275]) ("WavSoundFile" type "class" (("public" label ((reparse-symbol . classsubparts)) [317 324]) ("WavSoundFile" function ("WavSoundFile" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [340 358])) ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [327 359]) ("WavSoundFile" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [362 378]) ("read" function ("size_t" type "class") (("buffer" variable "void" nil ((pointer . 1)) nil nil [394 407]) ("buffer_size" variable ("size_t" type "class") nil nil nil nil [408 427])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [382 428]) ("reset" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [431 444]) ("private" label ((reparse-symbol . classsubparts)) [446 454]) ("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [457 475]) ("datastart" variable ("PHYSFS_sint64" type "class") nil nil nil nil [481 505])) (("SoundFile")) nil nil nil [277 508]) ("read32LE" function ("uint32_t" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [542 560])) ((typemodifiers "static" "inline")) nil nil [510 692]) ("read16LE" function ("uint16_t" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [726 744])) ((typemodifiers "static" "inline")) nil nil [694 876]) ("WavSoundFile" function ("WavSoundFile" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [905 923])) ((parent . "WavSoundFile") (constructor . t)) nil nil [878 3302]) ("WavSoundFile" function "void" nil ((parent . "WavSoundFile") (destructor . t)) nil nil [3304 3359]) ("reset" function ("void") nil ((parent . "WavSoundFile")) nil nil [3361 3492]) ("read" function ("size_t" type "class") (("buffer" variable "void" nil ((pointer . 1)) nil nil [3520 3533]) ("buffer_size" variable ("size_t" type "class") nil nil nil nil [3534 3553])) ((parent . "WavSoundFile")) nil nil [3494 3884]) ("OggSoundFile" type "class" (("public" label ((reparse-symbol . classsubparts)) [4005 4012]) ("OggSoundFile" function ("OggSoundFile" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [4028 4046])) ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [4015 4047]) ("OggSoundFile" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [4050 4066]) ("read" function ("size_t" type "class") (("buffer" variable "void" nil ((pointer . 1)) nil nil [4082 4095]) ("buffer_size" variable ("size_t" type "class") nil nil nil nil [4096 4115])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [4070 4116]) ("private" label ((reparse-symbol . classsubparts)) [4118 4126]) ("cb_read" function ("size_t" type "class") (("ptr" variable "void" nil ((pointer . 1)) nil nil [4151 4161]) ("size" variable ("size_t" type "class") nil nil nil nil [4162 4174]) ("nmemb" variable ("size_t" type "class") nil nil nil nil [4175 4188]) ("source" variable "void" nil ((pointer . 1)) nil nil [4189 4202])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [4129 4203]) ("cb_seek" function ("int") (("source" variable "void" nil ((pointer . 1)) nil nil [4225 4238]) ("offset" variable ("ogg_int64_t" type "class") nil nil nil nil [4239 4258]) ("whence" variable "int" nil nil nil nil [4259 4270])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [4206 4271]) ("cb_close" function ("int") (("source" variable "void" nil ((pointer . 1)) nil nil [4294 4307])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [4274 4308]) ("cb_tell" function ("long") (("source" variable "void" nil ((pointer . 1)) nil nil [4331 4344])) ((typemodifiers "static") (prototype . t)) nil ((reparse-symbol . classsubparts)) [4311 4345]) ("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [4351 4369]) ("vorbis_file" variable ("OggVorbis_File" type "class") nil nil nil nil [4372 4399])) (("SoundFile")) nil nil nil [3965 4402]) ("OggSoundFile" function ("OggSoundFile" type "class") (("file" variable ("PHYSFS_file" type "class") nil ((pointer . 1)) nil nil [4431 4449])) ((parent . "OggSoundFile") (constructor . t)) nil nil [4404 4786]) ("OggSoundFile" function "void" nil ((parent . "OggSoundFile") (destructor . t)) nil nil [4788 4847]) ("read" function ("size_t" type "class") (("_buffer" variable "void" nil ((pointer . 1)) nil nil [4875 4889]) ("buffer_size" variable ("size_t" type "class") nil nil nil nil [4890 4909])) ((parent . "OggSoundFile")) nil nil [4849 5318]) ("cb_read" function ("size_t" type "class") (("ptr" variable "void" nil ((pointer . 1)) nil nil [5349 5359]) ("size" variable ("size_t" type "class") nil nil nil nil [5360 5372]) ("nmemb" variable ("size_t" type "class") nil nil nil nil [5373 5386]) ("source" variable "void" nil ((pointer . 1)) nil nil [5387 5400])) ((parent . "OggSoundFile")) nil nil [5320 5666]) ("cb_seek" function ("int") (("source" variable "void" nil ((pointer . 1)) nil nil [5694 5707]) ("offset" variable ("ogg_int64_t" type "class") nil nil nil nil [5708 5727]) ("whence" variable "int" nil nil nil nil [5728 5739])) ((parent . "OggSoundFile")) nil nil [5668 6270]) ("cb_close" function ("int") (("source" variable "void" nil ((pointer . 1)) nil nil [6301 6314])) ((parent . "OggSoundFile")) nil nil [6274 6415]) ("cb_tell" function ("long") (("source" variable "void" nil ((pointer . 1)) nil nil [6444 6457])) ((parent . "OggSoundFile")) nil nil [6417 6572]) ("fstream" include t nil nil [6653 6671]) ("load_sound_file" function ("SoundFile" type "class") (("filename" variable ("std::string" type "class") nil ((const . t)) nil nil [6699 6727])) ((pointer . 1)) nil nil [6672 7441]))
:unmatched-syntax 'nil
)
)
--- /dev/null
+/** Used SDL_mixer and glest source as reference */
+#include <config.h>
+
+#include "sound_file.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <algorithm>
+#include <stdexcept>
+#include <sstream>
+#include <physfs.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+class WavSoundFile : public SoundFile
+{
+public:
+ WavSoundFile(PHYSFS_file* file);
+ ~WavSoundFile();
+
+ size_t read(void* buffer, size_t buffer_size);
+ void reset();
+
+private:
+ PHYSFS_file* file;
+
+ PHYSFS_sint64 datastart;
+};
+
+static inline uint32_t read32LE(PHYSFS_file* file)
+{
+ uint32_t result;
+ if(PHYSFS_readULE32(file, &result) == 0)
+ throw std::runtime_error("file too short");
+
+ return result;
+}
+
+static inline uint16_t read16LE(PHYSFS_file* file)
+{
+ uint16_t result;
+ if(PHYSFS_readULE16(file, &result) == 0)
+ throw std::runtime_error("file too short");
+
+ return result;
+}
+
+WavSoundFile::WavSoundFile(PHYSFS_file* file)
+{
+ this->file = file;
+
+ char magic[4];
+ if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1)
+ throw std::runtime_error("Couldn't read file magic (not a wave file)");
+ if(strncmp(magic, "RIFF", 4) != 0) {
+ printf("MAGIC: %4s.\n", magic);
+ throw std::runtime_error("file is not a RIFF wav file");
+ }
+
+ uint32_t wavelen = read32LE(file);
+ (void) wavelen;
+
+ if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1)
+ throw std::runtime_error("Couldn't read chunk header (not a wav file?)");
+ if(strncmp(magic, "WAVE", 4) != 0)
+ throw std::runtime_error("file is not a valid RIFF/WAVE file");
+
+ char chunkmagic[4];
+ uint32_t chunklen;
+
+ // search audio data format chunk
+ do {
+ if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1)
+ throw std::runtime_error("EOF while searching format chunk");
+ chunklen = read32LE(file);
+
+ if(strncmp(chunkmagic, "fmt ", 4) == 0)
+ break;
+
+ if(strncmp(chunkmagic, "fact", 4) == 0
+ || strncmp(chunkmagic, "LIST", 4) == 0) {
+ // skip chunk
+ if(PHYSFS_seek(file, PHYSFS_tell(file) + chunklen) == 0)
+ throw std::runtime_error("EOF while searching fmt chunk");
+ } else {
+ throw std::runtime_error("complex WAVE files not supported");
+ }
+ } while(true);
+
+ if(chunklen < 16)
+ throw std::runtime_error("Format chunk too short");
+
+ // parse format
+ uint16_t encoding = read16LE(file);
+ if(encoding != 1)
+ throw std::runtime_error("only PCM encoding supported");
+ channels = read16LE(file);
+ rate = read32LE(file);
+ uint32_t byterate = read32LE(file);
+ (void) byterate;
+ uint16_t blockalign = read16LE(file);
+ (void) blockalign;
+ bits_per_sample = read16LE(file);
+
+ if(chunklen > 16) {
+ if(PHYSFS_seek(file, PHYSFS_tell(file) + (chunklen-16)) == 0)
+ throw std::runtime_error("EOF while reading reast of format chunk");
+ }
+
+ // set file offset to DATA chunk data
+ do {
+ if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1)
+ throw std::runtime_error("EOF while searching data chunk");
+ chunklen = read32LE(file);
+
+ if(strncmp(chunkmagic, "data", 4) == 0)
+ break;
+
+ // skip chunk
+ if(PHYSFS_seek(file, PHYSFS_tell(file) + chunklen) == 0)
+ throw std::runtime_error("EOF while searching fmt chunk");
+ } while(true);
+
+ datastart = PHYSFS_tell(file);
+ size = static_cast<size_t> (chunklen);
+}
+
+WavSoundFile::~WavSoundFile()
+{
+ PHYSFS_close(file);
+}
+
+void
+WavSoundFile::reset()
+{
+ if(PHYSFS_seek(file, datastart) == 0)
+ throw std::runtime_error("Couldn't seek to data start");
+}
+
+size_t
+WavSoundFile::read(void* buffer, size_t buffer_size)
+{
+ PHYSFS_sint64 end = datastart + size;
+ PHYSFS_sint64 cur = PHYSFS_tell(file);
+ if(cur >= end)
+ return 0;
+
+ size_t readsize = std::min(static_cast<size_t> (end - cur), buffer_size);
+ if(PHYSFS_read(file, buffer, readsize, 1) != 1)
+ throw std::runtime_error("read error while reading samples");
+
+ return readsize;
+}
+
+//---------------------------------------------------------------------------
+
+class OggSoundFile : public SoundFile
+{
+public:
+ OggSoundFile(PHYSFS_file* file);
+ ~OggSoundFile();
+
+ size_t read(void* buffer, size_t buffer_size);
+ void reset();
+
+private:
+ static size_t cb_read(void* ptr, size_t size, size_t nmemb, void* source);
+ static int cb_seek(void* source, ogg_int64_t offset, int whence);
+ static int cb_close(void* source);
+ static long cb_tell(void* source);
+
+ PHYSFS_file* file;
+ OggVorbis_File vorbis_file;
+};
+
+OggSoundFile::OggSoundFile(PHYSFS_file* file)
+{
+ this->file = file;
+
+ ov_callbacks callbacks = { cb_read, cb_seek, cb_close, cb_tell };
+ ov_open_callbacks(file, &vorbis_file, 0, 0, callbacks);
+
+ vorbis_info* vi = ov_info(&vorbis_file, -1);
+ channels = vi->channels;
+ rate = vi->rate;
+ bits_per_sample = 16;
+ size = static_cast<size_t> (ov_pcm_total(&vorbis_file, -1) * 2);
+}
+
+OggSoundFile::~OggSoundFile()
+{
+ ov_clear(&vorbis_file);
+}
+
+size_t
+OggSoundFile::read(void* _buffer, size_t buffer_size)
+{
+ char* buffer = reinterpret_cast<char*> (_buffer);
+ int section = 0;
+ size_t totalBytesRead= 0;
+
+ while(buffer_size>0){
+ long bytesRead
+ = ov_read(&vorbis_file, buffer, static_cast<int> (buffer_size), 0, 2, 1,
+ §ion);
+ if(bytesRead==0){
+ break;
+ }
+ buffer_size -= bytesRead;
+ buffer += bytesRead;
+ totalBytesRead += bytesRead;
+ }
+
+ return totalBytesRead;
+}
+
+void
+OggSoundFile::reset()
+{
+ ov_raw_seek(&vorbis_file, 0);
+}
+
+size_t
+OggSoundFile::cb_read(void* ptr, size_t size, size_t nmemb, void* source)
+{
+ PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
+
+ PHYSFS_sint64 res
+ = PHYSFS_read(file, ptr, static_cast<PHYSFS_uint32> (size),
+ static_cast<PHYSFS_uint32> (nmemb));
+ if(res <= 0)
+ return 0;
+
+ return static_cast<size_t> (res);
+}
+
+int
+OggSoundFile::cb_seek(void* source, ogg_int64_t offset, int whence)
+{
+ PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
+
+ switch(whence) {
+ case SEEK_SET:
+ if(PHYSFS_seek(file, static_cast<PHYSFS_uint64> (offset)) == 0)
+ return -1;
+ break;
+ case SEEK_CUR:
+ if(PHYSFS_seek(file, PHYSFS_tell(file) + offset) == 0)
+ return -1;
+ break;
+ case SEEK_END:
+ if(PHYSFS_seek(file, PHYSFS_fileLength(file) + offset) == 0)
+ return -1;
+ break;
+ default:
+#ifdef DEBUG
+ assert(false);
+#else
+ return -1;
+#endif
+ }
+ return 0;
+}
+
+int
+OggSoundFile::cb_close(void* source)
+{
+ PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
+ PHYSFS_close(file);
+ return 0;
+}
+
+long
+OggSoundFile::cb_tell(void* source)
+{
+ PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
+ return static_cast<long> (PHYSFS_tell(file));
+}
+
+//---------------------------------------------------------------------------
+
+#include <fstream>
+SoundFile* load_sound_file(const std::string& filename)
+{
+ PHYSFS_file* file = PHYSFS_openRead(filename.c_str());
+ if(!file) {
+ std::stringstream msg;
+ msg << "Couldn't open '" << filename << "': " << PHYSFS_getLastError();
+ throw std::runtime_error(msg.str());
+ }
+
+ try {
+ char magic[4];
+ if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1)
+ throw std::runtime_error("Couldn't read magic, file too short");
+ PHYSFS_seek(file, 0);
+ if(strncmp(magic, "RIFF", 4) == 0)
+ return new WavSoundFile(file);
+ else if(strncmp(magic, "OggS", 4) == 0)
+ return new OggSoundFile(file);
+ else
+ throw std::runtime_error("Unknown file format");
+ } catch(std::exception& e) {
+ std::stringstream msg;
+ msg << "Couldn't read '" << filename << "': " << e.what();
+ throw std::runtime_error(msg.str());
+ }
+}
+
--- /dev/null
+#ifndef __SOUND_FILE_H__
+#define __SOUND_FILE_H__
+
+#include <stdio.h>
+#include <iostream>
+
+class SoundFile
+{
+public:
+ virtual ~SoundFile()
+ { }
+
+ virtual size_t read(void* buffer, size_t buffer_size) = 0;
+ virtual void reset() = 0;
+
+ int channels;
+ int rate;
+ int bits_per_sample;
+ /// size in bytes
+ size_t size;
+};
+
+SoundFile* load_sound_file(const std::string& filename);
+
+#endif
+
-// $Id: sound_manager.cpp 2334 2005-04-04 16:26:14Z grumbel $
-//
-// 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 <config.h>
-
-#include <cmath>
-#include <cassert>
-#include <iostream>
+#include "sound_manager.h"
+
#include <stdexcept>
+#include <iostream>
#include <sstream>
-#include <physfs.h>
+#include <memory>
-#include "audio/sound_manager.h"
-
-#include "audio/musicref.h"
-#include "physfs/physfs_sdl.h"
-#include "moving_object.h"
-#include "resources.h"
+#include "sound_file.h"
+#include "sound_source.h"
+#include "stream_sound_source.h"
SoundManager::SoundManager()
- : current_music(0), m_music_enabled(true) , m_sound_enabled(true),
- audio_device(false)
+ : device(0), context(0), sound_enabled(false), music_source(0)
{
+ try {
+ device = alcOpenDevice(0);
+ if(device == 0) {
+ print_openal_version();
+ throw std::runtime_error("Couldn't open audio device.");
+ }
+
+ int attributes[] = { 0 };
+ context = alcCreateContext(device, attributes);
+ check_alc_error("Couldn't create audio context: ");
+ alcMakeContextCurrent(context);
+ check_alc_error("Couldn't select audio context: ");
+
+ check_al_error("Audio error after init: ");
+ sound_enabled = true;
+ } catch(std::exception& e) {
+ device = 0;
+ context = 0;
+ std::cerr << "Couldn't initialize audio device:" << e.what() << "\n";
+ print_openal_version();
+ }
}
SoundManager::~SoundManager()
{
- for(Sounds::iterator i = sounds.begin(); i != sounds.end(); ++i) {
- Mix_FreeChunk(i->second);
- }
- sounds.clear();
-}
+ delete music_source;
-int
-SoundManager::play_sound(const std::string& name,int loops)
-{
- if(!audio_device || !m_sound_enabled)
- return -1;
-
- Mix_Chunk* chunk = preload_sound(name);
- if(chunk == 0) {
- std::cerr << "Sound '" << name << "' not found.\n";
- return -1;
+ for(SoundSources::iterator i = sources.begin(); i != sources.end(); ++i) {
+ delete *i;
}
- int chan=Mix_PlayChannel(-1, chunk, loops);
- Mix_Volume(chan,MIX_MAX_VOLUME);
- return chan;
-}
-
-int
-SoundManager::play_sound(const std::string& sound, const MovingObject* object,
- const Vector& pos)
-{
- // TODO keep track of the object later and move the sound along with the
- // object.
- return play_sound(sound, object->get_pos(), pos);
-}
-
-int
-SoundManager::play_sound(const std::string& sound, const Vector& pos,
- const Vector& pos2)
-{
- if(!audio_device || !m_sound_enabled)
- return -1;
-
- Mix_Chunk* chunk = preload_sound(sound);
- if(chunk == 0) {
- std::cerr << "Sound '" << sound << "' not found.\n";
- return -1;
+ for(SoundBuffers::iterator i = buffers.begin(); i != buffers.end(); ++i) {
+ ALuint buffer = i->second;
+ alDeleteBuffers(1, &buffer);
}
- // TODO make sure this formula is good
- float distance
- = pos2.x- pos.x;
- int loud = int(255.0/float(1600) * fabsf(distance));
- if(loud > 255)
- return -1;
-
- int chan = Mix_PlayChannel(-1, chunk, 0);
- if(chan < 0)
- return -1;
- Mix_Volume(chan,MIX_MAX_VOLUME);
- 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);
- return chan;
+ if(context != 0) {
+ alcMakeContextCurrent(0);
+ alcDestroyContext(context);
+ }
+ if(device != 0) {
+ alcCloseDevice(device);
+ }
}
-MusicRef
-SoundManager::load_music(const std::string& file)
+ALuint
+SoundManager::load_file_into_buffer(const std::string& filename)
{
- if(!audio_device)
- return MusicRef(0);
-
- if(!exists_music(file)) {
- std::stringstream msg;
- msg << "Couldn't load musicfile '" << file << "': " << SDL_GetError();
- throw std::runtime_error(msg.str());
+ // open sound file
+ std::auto_ptr<SoundFile> file (load_sound_file(filename));
+
+ ALenum format = get_sample_format(file.get());
+ ALuint buffer;
+ alGenBuffers(1, &buffer);
+ check_al_error("Couldn't create audio buffer: ");
+ char* samples = new char[file->size];
+ try {
+ file->read(samples, file->size);
+ alBufferData(buffer, format, samples,
+ static_cast<ALsizei> (file->size),
+ static_cast<ALsizei> (file->rate));
+ check_al_error("Couldn't fill audio buffer: ");
+ } catch(...) {
+ delete[] samples;
+ throw;
}
+ delete[] samples;
- std::map<std::string, MusicResource>::iterator i = musics.find(file);
- assert(i != musics.end());
- return MusicRef(& (i->second));
+ return buffer;
}
-bool
-SoundManager::exists_music(const std::string& filename)
+SoundSource*
+SoundManager::create_sound_source(const std::string& filename)
{
- if(!audio_device)
- return true;
+ if(!sound_enabled)
+ return 0;
+
+ ALuint buffer;
- // song already loaded?
- std::map<std::string, MusicResource>::iterator i = musics.find(filename);
- if(i != musics.end()) {
- return true;
+ // reuse an existing static sound buffer
+ SoundBuffers::iterator i = buffers.find(filename);
+ if(i != buffers.end()) {
+ buffer = i->second;
+ } else {
+ buffer = load_file_into_buffer(filename);
+ buffers.insert(std::make_pair(filename, buffer));
}
-
- const char* dir = PHYSFS_getRealDir(filename.c_str());
- if(dir == 0)
- return false;
- Mix_Music* song = Mix_LoadMUS( (std::string(dir) + "/" + filename).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> (filename, MusicResource()));
- MusicResource& resource = result.first->second;
- resource.manager = this;
- resource.music = song;
-
- return true;
+
+ SoundSource* source = new SoundSource();
+ alSourcei(source->source, AL_BUFFER, buffer);
+ return source;
}
void
-SoundManager::free_music(MusicResource* )
+SoundManager::play(const std::string& soundname, const Vector& pos)
{
- // 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.
+ std::string filename = "sounds/";
+ filename += soundname;
+ filename += ".wav";
+ try {
+ SoundSource* source = create_sound_source(filename);
+ if(source == 0)
+ return;
+ if(pos == Vector(-1, -1)) {
+ alSourcef(source->source, AL_ROLLOFF_FACTOR, 0);
+ } else {
+ source->set_position(pos);
+ }
+ source->play();
+ sources.push_back(source);
+ } catch(std::exception& e) {
+ std::cout << "Couldn't play sound " << filename << ": " << e.what() << "\n";
+ }
}
void
-SoundManager::play_music(const MusicRef& musicref, int loops)
+SoundManager::enable_sound(bool enable)
{
- if(!audio_device)
+ if(device == 0)
return;
-
- if(musicref.music == 0 || current_music == musicref.music)
- return;
-
- if(current_music)
- current_music->refcount--;
-
- current_music = musicref.music;
- current_music->refcount++;
-
- if(m_music_enabled)
- Mix_PlayMusic(current_music->music, loops);
+ sound_enabled = enable;
}
void
-SoundManager::halt_music()
+SoundManager::enable_music(bool enable)
{
- if(!audio_device)
+ if(device == 0)
return;
-
- Mix_HaltMusic();
-
- if(current_music) {
- current_music->refcount--;
- if(current_music->refcount == 0)
- free_music(current_music);
- current_music = 0;
+ music_enabled = enable;
+ if(music_enabled) {
+ play_music(current_music);
+ } else {
+ if(music_source) {
+ delete music_source;
+ music_source = 0;
+ }
}
}
void
-SoundManager::enable_music(bool enable)
+SoundManager::play_music(const std::string& filename)
{
- if(!audio_device)
+ if(filename == current_music)
return;
-
- if(enable == m_music_enabled)
+ current_music = filename;
+ if(!music_enabled)
return;
-
- m_music_enabled = enable;
- if(m_music_enabled == false) {
- Mix_HaltMusic();
- } else {
- if(current_music)
- Mix_PlayMusic(current_music->music, -1);
+
+ try {
+ StreamSoundSource* newmusic
+ = new StreamSoundSource(load_sound_file(filename));
+
+ alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0);
+ newmusic->play();
+
+ delete music_source;
+ music_source = newmusic;
+ } catch(std::exception& e) {
+ std::cerr << "Couldn't play music file '" << filename << "': "
+ << e.what() << "\n";
}
}
void
-SoundManager::enable_sound(bool enable)
+SoundManager::set_listener_position(Vector pos)
{
- if(!audio_device)
- return;
-
- m_sound_enabled = enable;
+ alListener3f(AL_POSITION, pos.x, pos.y, 0);
}
-SoundManager::MusicResource::~MusicResource()
+void
+SoundManager::set_listener_velocity(Vector vel)
{
- // don't free music buggy SDL_Mixer crashs for some mod files
- // Mix_FreeMusic(music);
+ alListener3f(AL_VELOCITY, vel.x, vel.y, 0);
}
-Mix_Chunk* SoundManager::preload_sound(const std::string& name)
+void
+SoundManager::update()
{
- if(!audio_device)
- return 0;
-
- Sounds::iterator i = sounds.find(name);
- if(i != sounds.end()) {
- return i->second;
+ // check for finished sound sources
+ for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) {
+ SoundSource* source = *i;
+ if(!source->playing()) {
+ delete source;
+ i = sources.erase(i);
+ } else {
+ ++i;
+ }
}
-
- std::string filename = "sounds/";
- filename += name;
- filename += ".wav";
+ // check streaming sounds
+ if(music_source)
+ music_source->update();
- Mix_Chunk* chunk = Mix_LoadWAV_RW(get_physfs_SDLRWops(filename), true);
- if(chunk != 0) {
- sounds.insert(std::make_pair(name, chunk));
+ alcProcessContext(context);
+ check_alc_error("Error while processing audio context: ");
+}
+
+ALenum
+SoundManager::get_sample_format(SoundFile* file)
+{
+ if(file->channels == 2) {
+ if(file->bits_per_sample == 16) {
+ return AL_FORMAT_STEREO16;
+ } else if(file->bits_per_sample == 8) {
+ return AL_FORMAT_STEREO8;
+ } else {
+ throw std::runtime_error("Only 16 and 8 bit samples supported");
+ }
+ } else if(file->channels == 1) {
+ if(file->bits_per_sample == 16) {
+ return AL_FORMAT_MONO16;
+ } else if(file->bits_per_sample == 8) {
+ return AL_FORMAT_MONO8;
+ } else {
+ throw std::runtime_error("Only 16 and 8 bit samples supported");
+ }
}
+
+ throw std::runtime_error("Only 1 and 2 channel samples supported");
+}
- return chunk;
+void
+SoundManager::print_openal_version()
+{
+ std::cout << "OpenAL Vendor: " << alGetString(AL_VENDOR) << "\n"
+ << "OpenAL Version: " << alGetString(AL_VERSION) << "\n"
+ << "OpenAL Renderer: " << alGetString(AL_RENDERER) << "\n"
+ << "OpenAl Extensions: " << alGetString(AL_RENDERER) << "\n";
+}
+
+void
+SoundManager::check_alc_error(const char* message)
+{
+ int err = alcGetError(device);
+ if(err != ALC_NO_ERROR) {
+ std::stringstream msg;
+ msg << message << alcGetString(device, err);
+ throw std::runtime_error(msg.str());
+ }
+}
+
+void
+SoundManager::check_al_error(const char* message)
+{
+ int err = alGetError();
+ if(err != AL_NO_ERROR) {
+ std::stringstream msg;
+ msg << message << alGetString(err);
+ throw std::runtime_error(msg.str());
+ }
}
-// $Id: sound_manager.h 2353 2005-04-06 23:00:16Z matzebraun $
-//
-// 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 SUPERTUX_SOUND_MANAGER_H
-#define SUPERTUX_SOUND_MANAGER_H
+#ifndef __SOUND_MANAGER_H__
+#define __SOUND_MANAGER_H__
+#include "math/vector.h"
#include <string>
#include <vector>
#include <map>
-#include "SDL_mixer.h"
-#include "math/vector.h"
+#include <AL/alc.h>
+#include <AL/al.h>
+
+typedef void* SoundHandle;
-class MusicRef;
-class MovingObject;
+class SoundFile;
+class SoundSource;
+class StreamSoundSource;
-/** Sound manager
- * This class handles all sounds that are played
- */
class SoundManager
{
public:
SoundManager();
- ~SoundManager();
-
- /// Play sound (maybe looping), return channel number (or -1 on error)
- int play_sound(const std::string& sound,int loops=0);
-
- /// Play sound relative to two Vectors.
- int play_sound(const std::string& sound, const Vector& pos,
- const Vector& pos2);
- /// Play sound relative to a MovingObject and a Vector.
- int play_sound(const std::string& sound, const MovingObject* object,
- const Vector& pos);
-
- /** Load music.
- * Is used to load the music for a MusicRef.
- */
- MusicRef load_music(const std::string& file);
+ virtual ~SoundManager();
+ void enable_sound(bool sound_enabled);
/**
- * If the sound isn't loaded yet try to load it.
- * Returns an existing instance of the sound, loads a new one and returns that
- * or returns 0 if loading failed.
+ * Creates a new sound source object which plays the specified soundfile.
+ * You are responsible for deleting the sound source later (this will stop the
+ * sound).
+ * This function might throw exceptions. It returns 0 if no audio device is
+ * available.
*/
- Mix_Chunk* preload_sound(const std::string& name);
+ SoundSource* create_sound_source(const std::string& filename);
+ /**
+ * Convenience function to simply play a sound at a given position.
+ * This functions constructs prepends sounds/ to the name and adds .wav
+ */
+ void play(const std::string& name, const Vector& pos = Vector(-1, -1));
- /// Test if a certain music file exists.
- bool exists_music(const std::string& filename);
+ void set_listener_position(Vector position);
+ void set_listener_velocity(Vector velocity);
- /** Play music.
- * @param loops: Defaults to -1, which means endless loops.
- */
- void play_music(const MusicRef& music, int loops = -1);
+ void enable_music(bool music_enabled);
+ void play_music(const std::string& filename);
- /// Halt music.
- void halt_music();
+ void update();
- /// Enable/Disable music.
- void enable_music(bool enable);
+private:
+ friend class SoundSource;
+ friend class StreamSoundSource;
- /// Is music enabled?
- bool music_enabled()
- {
- return m_music_enabled;
- }
+ static ALuint load_file_into_buffer(const std::string& filename);
+ static ALenum get_sample_format(SoundFile* file);
- /// Enable/Disable sound.
- void enable_sound(bool enable);
+ void print_openal_version();
+ void check_alc_error(const char* message);
+ static void check_al_error(const char* message);
- /// Is sound enabled?
- bool sound_enabled()
- {
- return m_sound_enabled;
- }
+ ALCdevice* device;
+ ALCcontext* context;
+ bool sound_enabled;
- /// Is audio available?
- bool audio_device_available()
- {
- return audio_device;
- }
+ typedef std::map<std::string, ALuint> SoundBuffers;
+ SoundBuffers buffers;
+ typedef std::vector<SoundSource*> SoundSources;
+ SoundSources sources;
- void set_audio_device_available(bool available)
- {
- audio_device = available;
- }
+ StreamSoundSource* music_source;
-private:
- friend class MusicRef;
- friend class Setup;
-
- /// Resource for music.
- /** Contains the raw music data and
- information for music reference
- counting. */
- class MusicResource
- {
- public:
- ~MusicResource();
-
- SoundManager* manager;
- Mix_Music* music;
- int refcount;
- };
-
- void free_music(MusicResource* music);
-
- typedef std::map<std::string, Mix_Chunk*> Sounds;
- Sounds sounds;
-
- typedef std::map<std::string, MusicResource> Musics;
- Musics musics;
-
- MusicResource* current_music;
- bool m_music_enabled;
- bool m_sound_enabled;
- bool audio_device; /* true: available and initialized */
+ bool music_enabled;
+ std::string current_music;
};
-#endif /*SUPERTUX_SOUND_MANAGER_H*/
+#endif
--- /dev/null
+#include <config.h>
+
+#include "sound_source.h"
+#include "sound_manager.h"
+
+SoundSource::SoundSource()
+{
+ alGenSources(1, &source);
+ SoundManager::check_al_error("Couldn't create audio source: ");
+ set_reference_distance(128);
+}
+
+SoundSource::~SoundSource()
+{
+ stop();
+ alDeleteSources(1, &source);
+}
+
+void
+SoundSource::stop()
+{
+ alSourceStop(source);
+ alSourcei(source, AL_BUFFER, AL_NONE);
+ SoundManager::check_al_error("Problem stopping audio source: ");
+}
+
+void
+SoundSource::play()
+{
+ alSourcePlay(source);
+ SoundManager::check_al_error("Couldn't start audio source: ");
+}
+
+bool
+SoundSource::playing()
+{
+ ALint state = AL_PLAYING;
+ alGetSourcei(source, AL_SOURCE_STATE, &state);
+ return state != AL_STOPPED;
+}
+
+void
+SoundSource::set_looping(bool looping)
+{
+ alSourcei(source, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
+}
+
+void
+SoundSource::set_position(Vector position)
+{
+ alSource3f(source, AL_POSITION, position.x, position.y, 0);
+}
+
+void
+SoundSource::set_velocity(Vector velocity)
+{
+ alSource3f(source, AL_VELOCITY, velocity.x, velocity.y, 0);
+}
+
+void
+SoundSource::set_gain(float gain)
+{
+ alSourcef(source, AL_GAIN, gain);
+}
+
+void
+SoundSource::set_reference_distance(float distance)
+{
+ alSourcef(source, AL_REFERENCE_DISTANCE, distance);
+}
--- /dev/null
+#ifndef __SOUND_SOURCE_H__
+#define __SOUND_SOURCE_H__
+
+#include <AL/al.h>
+#include "math/vector.h"
+
+class SoundSource
+{
+public:
+ SoundSource();
+ virtual ~SoundSource();
+
+ void play();
+ void stop();
+ bool playing();
+
+ void set_looping(bool looping);
+ /// Set volume (0.0 is silent, 1.0 is normal)
+ void set_gain(float gain);
+ void set_position(Vector position);
+ void set_velocity(Vector position);
+ void set_reference_distance(float distance);
+
+protected:
+ friend class SoundManager;
+
+ ALuint source;
+};
+
+#endif
+
--- /dev/null
+#include <config.h>
+
+#include "stream_sound_source.h"
+#include "sound_manager.h"
+#include "sound_file.h"
+
+StreamSoundSource::StreamSoundSource(SoundFile* file)
+{
+ this->file = file;
+ alGenBuffers(STREAMFRAGMENTS, buffers);
+ SoundManager::check_al_error("Couldn't allocate audio buffers: ");
+ format = SoundManager::get_sample_format(file);
+ try {
+ for(size_t i = 0; i < STREAMFRAGMENTS; ++i) {
+ fillBufferAndQueue(buffers[i]);
+ }
+ } catch(...) {
+ alDeleteBuffers(STREAMFRAGMENTS, buffers);
+ }
+}
+
+StreamSoundSource::~StreamSoundSource()
+{
+ alDeleteBuffers(STREAMFRAGMENTS, buffers);
+ SoundManager::check_al_error("Couldn't delete audio buffers: ");
+}
+
+void
+StreamSoundSource::update()
+{
+ if(!playing())
+ return;
+
+ ALint processed = 0;
+ alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
+ while(processed > 0) {
+ processed--;
+
+ ALuint buffer;
+ alSourceUnqueueBuffers(source, 1, &buffer);
+ SoundManager::check_al_error("Couldn't unqueu audio buffer: ");
+
+ fillBufferAndQueue(buffer);
+ }
+
+ // we might have to restart the source if we had a buffer underrun
+ if(!playing()) {
+ std::cerr << "Restarting audio source because of buffer underrun.\n";
+ alSourcePlay(source);
+ SoundManager::check_al_error("Couldn't restart audio source: ");
+ }
+
+ // TODO handle fading
+}
+
+void
+StreamSoundSource::fillBufferAndQueue(ALuint buffer)
+{
+ // fill buffer
+ char* bufferdata = new char[STREAMFRAGMENTSIZE];
+ size_t bytesread = 0;
+ do {
+ bytesread += file->read(bufferdata + bytesread,
+ STREAMFRAGMENTSIZE - bytesread);
+ if(bytesread < STREAMFRAGMENTSIZE) {
+ file->reset();
+ }
+ } while(bytesread < STREAMFRAGMENTSIZE);
+
+ alBufferData(buffer, format, bufferdata, STREAMFRAGMENTSIZE, file->rate);
+ delete[] bufferdata;
+ SoundManager::check_al_error("Couldn't refill audio buffer: ");
+
+ alSourceQueueBuffers(source, 1, &buffer);
+ SoundManager::check_al_error("Couldn't queue audio buffer: ");
+}
--- /dev/null
+#ifndef __STREAM_SOUND_SOURCE_H__
+#define __STREAM_SOUND_SOURCE_H__
+
+#include <stdio.h>
+#include "sound_source.h"
+
+class SoundFile;
+
+class StreamSoundSource : public SoundSource
+{
+public:
+ StreamSoundSource(SoundFile* file);
+ virtual ~StreamSoundSource();
+
+ void update();
+
+private:
+ static const size_t STREAMBUFFERSIZE = 1024 * 500;
+ static const size_t STREAMFRAGMENTS = 5;
+ static const size_t STREAMFRAGMENTSIZE
+ = STREAMBUFFERSIZE / STREAMFRAGMENTS;
+
+ void fillBufferAndQueue(ALuint buffer);
+ SoundFile* file;
+ ALuint buffers[STREAMFRAGMENTS];
+ ALenum format;
+
+ enum FadeState { NoFading, FadingOn, FadingOff };
+ FadeState fade_state;
+ // TODO
+};
+
+#endif
+
void
BadGuy::kill_squished(Player& player)
{
- sound_manager->play_sound("squish", get_pos(), player.get_pos());
+ sound_manager->play("squish", get_pos());
physic.enable_gravity(true);
physic.set_velocity_x(0);
physic.set_velocity_y(0);
void
BadGuy::kill_fall()
{
- sound_manager->play_sound("fall", this,
- Sector::current()->player->get_pos());
+ sound_manager->play("fall", get_pos());
global_stats.add_points(BADGUYS_KILLED_STAT, 1);
physic.set_velocity_y(0);
physic.enable_gravity(true);
#include "lisp/lisp.h"
#include "lisp/writer.h"
#include "video/drawing_context.h"
+#include "audio/sound_manager.h"
+#include "audio/sound_source.h"
#include "sprite/sprite_manager.h"
class BadGuy : public MovingObject, public Serializable
{
state = 1;
sprite->set_action("explosion");
- sound_manager->play_sound("explosion", get_pos(),
- Sector::current()->player->get_pos());
+ sound_manager->play("explosion", get_pos());
timer.start(EXPLOSIONTIME);
}
#include "flame.h"
Flame::Flame(const lisp::Lisp& reader)
- : angle(0), radius(100), speed(2)
+ : angle(0), radius(100), speed(2), source(0)
{
reader.get("x", start_position.x);
reader.get("y", start_position.y);
countMe = false;
}
+Flame::~Flame()
+{
+ delete source;
+}
+
void
Flame::write(lisp::Writer& writer)
{
Vector newpos(start_position.x + cos(angle) * radius,
start_position.y + sin(angle) * radius);
movement = newpos - get_pos();
+
+ source->set_position(get_pos());
+}
+
+void
+Flame::activate()
+{
+ delete source;
+ source = sound_manager->create_sound_source("sounds/flame.wav");
+ if(!source) {
+ std::cerr << "Couldn't start flame sound.\n";
+ return;
+ }
+ source->set_position(get_pos());
+ source->set_looping(true);
+ source->set_gain(2.0);
+ source->set_reference_distance(32);
+ source->play();
+}
+
+void
+Flame::deactivate()
+{
+ delete source;
+ source = 0;
}
void
{
public:
Flame(const lisp::Lisp& reader);
+ ~Flame();
+
+ void activate();
+ void deactivate();
void write(lisp::Writer& write);
void active_update(float elapsed_time);
float angle;
float radius;
float speed;
+
+ SoundSource* source;
};
#endif
physic.set_velocity_y(JUMPSPEED);
// TODO create a nice sound for this...
- //sound_manager->play_sound("skid");
+ //sound_manager->play("skid");
} else if(chit.normal.y < .5) { // bumped on roof
physic.set_velocity_y(0);
}
dir = dir == LEFT ? RIGHT : LEFT;
sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
physic.set_velocity_x(-physic.get_velocity_x());
- sound_manager->play_sound("ricochet", get_pos(),
- Sector::current()->player->get_pos());
+ sound_manager->play("ricochet", get_pos());
break;
}
case ICESTATE_FLAT:
}
// flatten
- sound_manager->play_sound("stomp", get_pos(), player.get_pos());
+ sound_manager->play("stomp", get_pos());
physic.set_velocity_x(0);
physic.set_velocity_y(0);
break;
case ICESTATE_FLAT:
// kick
- sound_manager->play_sound("kick", this, player.get_pos());
+ sound_manager->play("kick", get_pos());
if(player.get_pos().x < get_pos().x) {
dir = RIGHT;
mystate = STATE_NORMAL;
activate();
- sound_manager->play_sound("squish", get_pos(), player.get_pos());
+ sound_manager->play("squish", get_pos());
player.bounce(*this);
} else {
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
bullet_hitpoints--;
if (bullet_hitpoints <= 0) {
hitpoints = 0;
- sound_manager->play_sound("fall", this,
+ sound_manager->play("fall", this,
Sector::current()->player->get_pos());
physic.set_velocity_y(0);
physic.enable_gravity(true);
RocketExplosion::explode()
{
sprite->set_action(dir == LEFT ? "explosion-left" : "explosion-right");
- sound_manager->play_sound("explosion", get_pos(),
- Sector::current()->player->get_pos());
+ sound_manager->play("explosion", get_pos());
timer.start(EXPLOSIONTIME, true);
}
void
RocketExplosion::kill_fall()
{
- explode();
}
sprite->set_action("right");
state = INIT;
side = LEFT;
+#if 0
sound_manager->preload_sound("yeti_gna");
sound_manager->preload_sound("yeti_roar");
+#endif
hit_points = INITIAL_HITPOINTS;
reader.get("dead-script", dead_script);
countMe = false;
case ANGRY_JUMPING:
if(timer.check()) {
// jump
- sound_manager->play_sound("yeti_gna");
+ sound_manager->play("yeti_gna");
physic.set_velocity_y(JUMP_VEL1);
}
break;
return true;
player.bounce(*this);
- sound_manager->play_sound("yeti_roar");
+ sound_manager->play("yeti_roar");
hit_points--;
if(hit_points <= 0) {
sprite->set_action("dead");
friend class KeyboardMenu;
friend class JoystickMenu;
- char last_keys[20];
+ char last_keys[20];
};
#endif
#include <SDL.h>
-#ifndef WIN32
-#include <sys/types.h>
-#include <ctype.h>
-#endif
-
#include "game_session.h"
#include "video/screen.h"
+#include "audio/sound_manager.h"
#include "gui/menu.h"
#include "sector.h"
#include "level.h"
newsector = "";
newspawnpoint = "";
}
+
+ // update sounds
+ sound_manager->set_listener_position(currentsector->player->get_pos());
+ sound_manager->update();
}
void
end_sequence = ENDSEQUENCE_RUNNING;
endsequence_timer.start(7.0); // 7 seconds until we finish the map
last_x_pos = -1;
- sound_manager->play_music(level_end_song, 0);
+ sound_manager->play_music("music/leveldone.mod");
currentsector->player->invincible_timer.start(7.0);
if(sequencename == "fireworks") {
#include <sstream>
#include <fstream>
-#include "audio/sound_manager.h"
#include "lisp/parser.h"
#include "lisp/lisp.h"
#include "lisp/writer.h"
screenwidth = 800;
screenheight = 600;
use_gl = true;
-
- audio_frequency = MIX_DEFAULT_FREQUENCY;
- audio_channels = MIX_DEFAULT_CHANNELS;
- audio_chunksize = 2048;
- audio_voices = MIX_CHANNELS;
}
Config::~Config()
if(config_audio_lisp) {
config_audio_lisp->get("sound_enabled", sound_enabled);
config_audio_lisp->get("music_enabled", music_enabled);
- config_audio_lisp->get("frequency", audio_frequency);
- config_audio_lisp->get("channels", audio_channels);
- config_audio_lisp->get("voices", audio_voices);
- config_audio_lisp->get("chunksize", audio_chunksize);
}
const lisp::Lisp* config_control_lisp = config_lisp->get_lisp("control");
writer.start_list("audio");
writer.write_bool("sound_enabled", sound_enabled);
writer.write_bool("music_enabled", music_enabled);
- writer.write_int("frequency", audio_frequency);
- writer.write_int("channels", audio_channels);
- writer.write_int("voices", audio_voices);
- writer.write_int("chunksize", audio_chunksize);
writer.end_list("audio");
if(main_controller) {
int screenheight;
bool use_gl;
- int audio_frequency;
- int audio_channels;
- int audio_voices;
- int audio_chunksize;
-
bool use_fullscreen;
bool show_fps;
bool sound_enabled;
+++ /dev/null
-// $Id$
-//
-// SuperTux
-// Copyright (C) 2005 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.
-
-/***************************************************************************
- leveleditor.cpp - built'in leveleditor
- -------------------
- begin : June, 23 2004
- copyright : (C) 2004 by Ricardo Cruz
- email : rick2@aeiou.pt
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-#if 0
-#include <config.h>
-
-#include <stdlib.h>
-#include <algorithm>
-
-#include "gui/mousecursor.h"
-#include "gui/menu.h"
-#include "gui/button.h"
-#include "audio/sound_manager.h"
-#include "app/gettext.h"
-#include "sprite/sprite.h"
-#include "leveleditor.h"
-#include "resources.h"
-#include "tile.h"
-#include "tile_manager.h"
-#include "sector.h"
-#include "game_session.h"
-#include "object_factory.h"
-#include "object/gameobjs.h"
-#include "object/camera.h"
-#include "object/tilemap.h"
-#include "object/background.h"
-
-LevelEditor::LevelEditor()
-{
- show_grid = true;
-
- selection.clear();
- selection_end = selection_ini = Vector(0,0);
- left_button = middle_button = mouse_moved = false;
- level = 0;
- level_subset = 0;
-
- cur_layer = LAYER_TILES;
- level_changed = false;
-
- sector = 0;
- zoom = 1.0;
-
- /* Creating menus */
- level_subsets = FileSystem::dsubdirs("/levels", "info");
- subset_menu = new Menu();
- subset_menu->add_label(_("Load Subset"));
- subset_menu->additem(MN_HL,"",0,0);
- int i = 0;
- for(std::set<std::string>::iterator it = level_subsets.begin(); it != level_subsets.end(); ++it, ++i)
- subset_menu->additem(MN_ACTION, (*it),0,0,i);
- subset_menu->additem(MN_HL,"",0,0);
- subset_menu->additem(MN_BACK,_("Back"),0,0);
-
- create_subset_menu = new Menu();
- create_subset_menu->additem(MN_LABEL,_("New Level Subset"),0,0);
- create_subset_menu->additem(MN_HL,"",0,0);
- create_subset_menu->additem(MN_TEXTFIELD,_("Filename "),0,0,MN_ID_FILENAME_SUBSET);
- create_subset_menu->additem(MN_TEXTFIELD,_("Title "),0,0,MN_ID_TITLE_SUBSET);
- create_subset_menu->additem(MN_TEXTFIELD,_("Description"),0,0,MN_ID_DESCRIPTION_SUBSET);
- create_subset_menu->additem(MN_ACTION,_("Create"),0,0, MN_ID_CREATE_SUBSET);
- create_subset_menu->additem(MN_HL,"",0,0);
- create_subset_menu->additem(MN_BACK,_("Back"),0,0);
-
- main_menu = new Menu();
- main_menu->additem(MN_LABEL,_("Level Editor Menu"),0,0);
- main_menu->additem(MN_HL,"",0,0);
- main_menu->additem(MN_ACTION,_("Return to Level Editor"),0,0,MN_ID_RETURN);
- main_menu->additem(MN_GOTO,_("Create Level Subset"),0,create_subset_menu);
- main_menu->additem(MN_GOTO,_("Load Level Subset"),0,subset_menu);
- main_menu->additem(MN_HL,"",0,0);
- main_menu->additem(MN_ACTION,_("Quit Level Editor"),0,0,MN_ID_QUIT);
-
- settings_menu = new Menu();
- settings_menu->additem(MN_LABEL,_("Level Settings"),0,0);
- settings_menu->additem(MN_HL,"",0,0);
- settings_menu->additem(MN_TEXTFIELD,_("Name "),0,0,MN_ID_NAME);
- settings_menu->additem(MN_TEXTFIELD,_("Author "),0,0,MN_ID_AUTHOR);
- settings_menu->additem(MN_NUMFIELD, _("Width "),0,0,MN_ID_WIDTH);
- settings_menu->additem(MN_NUMFIELD, _("Height "),0,0,MN_ID_HEIGHT);
- settings_menu->additem(MN_HL,"",0,0);
- settings_menu->additem(MN_ACTION,_("Apply"),0,0,MN_ID_APPLY_SETTINGS);
-
- /* Creating button groups */
- load_buttons_gfx();
-
- tiles_board = new ButtonGroup(Vector(SCREEN_WIDTH - 140, 100),
- Vector(32,32), Vector(4,8));
-
- tiles_board->add_button(Button(img_rubber_bt, _("Eraser"), SDLKey(SDLK_DELETE)), 0);
- unsigned int id;
- for(id = 1; id < tile_manager->get_max_tileid(); id++)
- {
- const Tile* tile = tile_manager->get(id);
- if(!tile)
- continue;
-
- Surface* surface = tile->get_editor_image();
- if(!surface)
- continue;
-
- Button button = Button(surface, "", SDLKey(0));
- tiles_board->add_button(button, id);
- }
- gameobjs_first_id = id;
-
- for(Factories::iterator i = object_factories->begin();
- i != object_factories->end(); ++i) {
-
-// Surface *img = badguy.get_image();
-// FIXME: get image from object. Using the rubber in the meanwhile.
- tiles_board->add_button(Button(img_rubber_bt, i->first,
- SDLKey(SDLK_1+id)), id++);
- }
-
- tiles_layer = new ButtonGroup(Vector(12, SCREEN_HEIGHT-64), Vector(80,20), Vector(1,3));
- tiles_layer->add_button(Button(img_foreground_bt, _("Edtit foreground tiles"),
- SDLK_F10), LAYER_FOREGROUNDTILES);
- tiles_layer->add_button(Button(img_interactive_bt, _("Edit interactive tiles"),
- SDLK_F11), LAYER_TILES, true);
- tiles_layer->add_button(Button(img_background_bt, _("Edit background tiles"),
- SDLK_F12), LAYER_BACKGROUNDTILES);
-
- level_options = new ButtonGroup(Vector(SCREEN_WIDTH-164, SCREEN_HEIGHT-36), Vector(32,32), Vector(5,1));
- level_options->add_pair_of_buttons(Button(img_next_sector_bt, _("Next sector"), SDLKey(0)), BT_NEXT_SECTOR,
- Button(img_previous_sector_bt, _("Prevous sector"), SDLKey(0)), BT_PREVIOUS_SECTOR);
- level_options->add_pair_of_buttons(Button(img_next_level_bt, _("Next level"), SDLKey(0)), BT_NEXT_LEVEL,
- Button(img_previous_level_bt, _("Prevous level"), SDLKey(0)), BT_PREVIOUS_LEVEL);
- level_options->add_button(Button(img_save_level_bt, _("Save level"), SDLK_F5), BT_LEVEL_SAVE);
- level_options->add_button(Button(img_test_level_bt, _("Test level"), SDLK_F6), BT_LEVEL_TEST);
- level_options->add_button(Button(img_setup_level_bt, _("Setup level"), SDLK_F7), BT_LEVEL_SETUP);
-}
-
-LevelEditor::~LevelEditor()
-{
-free_buttons_gfx();
-
-delete tiles_board;
-delete tiles_layer;
-delete level_options;
-
-delete subset_menu;
-delete create_subset_menu;
-delete main_menu;
-delete settings_menu;
-
-delete level;
-delete level_subset;
-}
-
-void LevelEditor::load_buttons_gfx()
-{
-img_foreground_bt = new Surface(datadir + "/images/leveleditor/foreground.png", true);
-img_interactive_bt = new Surface(datadir + "/images/leveleditor/interactive.png", true);
-img_background_bt = new Surface(datadir + "/images/leveleditor/background.png", true);
-
-img_save_level_bt = new Surface(datadir + "/images/leveleditor/save-level.png", true);
-img_test_level_bt = new Surface(datadir + "/images/leveleditor/test-level.png", true);
-img_setup_level_bt = new Surface(datadir + "/images/leveleditor/setup-level.png", true);
-
-img_rubber_bt = new Surface(datadir + "/images/leveleditor/rubber.png", true);
-
-img_previous_level_bt = new Surface(datadir + "/images/leveleditor/previous-level.png", true);
-img_next_level_bt = new Surface(datadir + "/images/leveleditor/next-level.png", true);
-img_previous_sector_bt = new Surface(datadir + "/images/leveleditor/previous-sector.png", true);
-img_next_sector_bt = new Surface(datadir + "/images/leveleditor/next-sector.png", true);
-}
-
-void LevelEditor::free_buttons_gfx()
-{
-delete img_foreground_bt;
-delete img_interactive_bt;
-delete img_background_bt;
-
-delete img_save_level_bt;
-delete img_test_level_bt;
-delete img_setup_level_bt;
-
-delete img_rubber_bt;
-
-delete img_previous_level_bt;
-delete img_next_level_bt;
-delete img_previous_sector_bt;
-delete img_next_sector_bt;
-}
-
-void LevelEditor::run(const std::string filename)
-{
- sound_manager->halt_music();
- Menu::set_current(0);
-
- DrawingContext context;
-
- if(!filename.empty())
- {
- level_nb = -1;
- load_level(filename);
- }
- else
- Menu::set_current(main_menu);
-
- mouse_cursor->set_state(MC_NORMAL);
-
- done = false;
- while(!done)
- {
- events();
- action();
- draw(context);
- }
-
- if(level_changed)
- if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
- save_level();
-}
-
-void LevelEditor::events()
-{
- mouse_moved = false;
-
- SDL_Event event;
- while(SDL_PollEvent(&event))
- {
- Menu* menu = Menu::current();
- if(menu)
- {
- menu->event(event);
- menu->action();
- if(menu == main_menu)
- {
- switch (main_menu->check())
- {
- case MN_ID_RETURN:
- Menu::set_current(0);
- break;
- case MN_ID_QUIT:
- done = true;
- break;
- }
- }
- else if(menu == create_subset_menu)
- {
- // activate or deactivate Create button if any filename as been specified
- if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0')
- create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE;
- else
- create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_ACTION;
-
- if(create_subset_menu->check() == MN_ID_CREATE_SUBSET)
- { // applying settings:
- std::string subset_name = create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input;
- LevelSubset::create(subset_name);
-
- delete level_subset;
- level_subset = new LevelSubset();
- level_subset->load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input);
-
- level_subset->title = create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).input;
- level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input;
- //FIXME: generate better level filenames
- level_subset->add_level(subset_name+'/'+"new_level.stl");
- Level* newlevel = new Level();
- newlevel->add_sector(create_sector("main", 25, 19));
- newlevel->save(level_subset->get_level_filename(0));
- level_subset->save();
-
- load_level(0);
-
- create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input("");
- create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input("");
- create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input("");
- }
- }
- else if(menu == subset_menu)
- {
- int i = subset_menu->check();
- if(i >= 0)
- {
- std::set<std::string>::iterator it = level_subsets.begin();
- for(int t = 0; t < i; t++)
- it++;
- load_level_subset(*it);
- Menu::set_current(0);
- }
- }
- else if(menu == settings_menu)
- {
- if(settings_menu->check() == MN_ID_APPLY_SETTINGS)
- { // applying settings:
- level_changed = true;
-
- level->name = settings_menu->get_item_by_id(MN_ID_NAME).input;
- level->author = settings_menu->get_item_by_id(MN_ID_AUTHOR).input;
-
- solids->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()),
- atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str()));
- foregrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()),
- atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str()));
- backgrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()),
- atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str()));
-
- Menu::set_current(0);
- }
- }
- }
- // check for events in buttons
- else if(tiles_board->event(event))
- {
- std::vector <int> vector;
- vector.push_back(tiles_board->selected_id());
-
- selection.clear();
- selection.push_back(vector);
- continue;
- }
- else if(tiles_layer->event(event))
- {
- cur_layer = tiles_layer->selected_id();
- continue;
- }
- else if(level_options->event(event))
- {
- switch(level_options->selected_id())
- {
- case BT_LEVEL_SAVE:
- save_level();
- break;
- case BT_LEVEL_TEST:
- test_level();
- break;
- case BT_LEVEL_SETUP:
- Menu::set_current(settings_menu);
- break;
- case BT_NEXT_LEVEL:
- if(level_nb + 1 < level_subset->get_num_levels())
- load_level(level_nb + 1);
- else
- {
- char str[1024];
- sprintf(str,_("Level %d doesn't exist. Create it?"), level_nb + 2);
- if(confirm_dialog(NULL, str))
- {
- level_subset->add_level("new_level.stl");
- Level* newlevel = new Level();
- newlevel->add_sector(create_sector("main", 25, 19));
- newlevel->save(level_subset->get_level_filename(level_nb + 1));
- level_subset->save();
- load_level(level_nb + 1);
- }
- }
- break;
- case BT_PREVIOUS_LEVEL:
- if(level_nb - 1 >= 0)
- load_level(level_nb - 1);
- break;
- case BT_NEXT_SECTOR:
- std::cerr << "next sector.\n";
- load_sector(sectornum+1);
- break;
- case BT_PREVIOUS_SECTOR:
- std::cerr << "previous sector.\n";
- if(sectornum > 0)
- load_sector(sectornum-1);
- break;
- }
- level_options->set_unselected();
- continue;
- }
- else
- {
- switch(event.type)
- {
- case SDL_MOUSEMOTION:
- mouse_moved = true;
- mouse_x = event.motion.x;
- mouse_y = event.motion.y;
- if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT))
- { // movement like in strategy games
- scroll.x += -1 * event.motion.xrel;
- scroll.y += -1 * event.motion.yrel;
- }
- break;
-
- case SDL_MOUSEBUTTONDOWN:
- mouse_moved = true;
- mouse_x = event.motion.x;
- mouse_y = event.motion.y;
- if(event.button.button == SDL_BUTTON_LEFT)
- left_button = true;
- else if(event.button.button == SDL_BUTTON_MIDDLE)
- {
- middle_button = true;
- selection_ini = Vector(event.button.x, event.button.y);
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- mouse_moved = true;
- mouse_x = event.motion.x;
- mouse_y = event.motion.y;
- if(event.button.button == SDL_BUTTON_LEFT)
- left_button = false;
- else if(event.button.button == SDL_BUTTON_MIDDLE)
- {
- middle_button = false;
- selection_end = Vector(event.button.x, event.button.y);
-
- if(selection_end.x < selection_ini.x)
- {
- float t = selection_ini.x;
- selection_ini.x = selection_end.x;
- selection_end.x = t;
- }
- if(selection_end.y < selection_ini.y)
- {
- float t = selection_ini.y;
- selection_ini.y = selection_end.y;
- selection_end.y = t;
- }
-
- selection.clear();
- std::vector <int> vector;
-
- TileMap* tilemap = 0;
- if(cur_layer == LAYER_FOREGROUNDTILES)
- tilemap = foregrounds;
- else if(cur_layer == LAYER_TILES)
- tilemap = solids;
- else if(cur_layer == LAYER_BACKGROUNDTILES)
- tilemap = backgrounds;
-
- for(int x = 0; x < (int)((selection_end.x - selection_ini.x)*zoom / 32) + 1; x++)
- {
- vector.clear();
- for(int y = 0; y < (int)((selection_end.y - selection_ini.y)*zoom / 32) + 1; y++)
- {
- vector.push_back(tilemap->get_tile(x +
- (int)(((selection_ini.x+scroll.x)*zoom)/32),
- y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->getID());
- }
- selection.push_back(vector);
- }
- }
- break;
-
- case SDL_KEYDOWN: // key pressed
- switch(event.key.keysym.sym)
- {
- case SDLK_ESCAPE:
- Menu::set_current(main_menu);
- break;
- /* scrolling related events: */
- case SDLK_HOME:
- scroll.x = 0;
- break;
- case SDLK_END:
- scroll.x = sector->solids->get_height()*32 - SCREEN_WIDTH;
- break;
- case SDLK_LEFT:
- scroll.x -= 80;
- break;
- case SDLK_RIGHT:
- scroll.x += 80;
- break;
- case SDLK_UP:
- scroll.y -= 80;
- break;
- case SDLK_DOWN:
- scroll.y += 80;
- break;
- case SDLK_PAGEUP:
- scroll.x -= 450;
- break;
- case SDLK_PAGEDOWN:
- scroll.x += 450;
- break;
- case SDLK_PLUS:
- case SDLK_KP_PLUS:
- zoom += 0.10;
- break;
- case SDLK_MINUS:
- case SDLK_KP_MINUS:
- zoom -= 0.10;
- break;
-
- case SDLK_F1:
- show_help();
- break;
- case SDLK_F2:
- show_grid = !show_grid;
- break;
- default:
- break;
- }
- break;
-
- case SDL_QUIT: // window closed
- done = true;
- break;
-
- default:
- break;
- }
- }
- }
-}
-
-void LevelEditor::action()
-{
- mouse_cursor->set_state(MC_NORMAL);
- if(tiles_board->is_hover() || tiles_layer->is_hover() || level_options->is_hover())
- mouse_cursor->set_state(MC_LINK);
-
- if(sector)
- {
- // don't scroll before the start or after the level's end
- float width = sector->solids->get_width() * 32;
- float height = sector->solids->get_height() * 32;
-
- if(scroll.x < -SCREEN_WIDTH/2)
- scroll.x = -SCREEN_WIDTH/2;
- if(scroll.x > width - SCREEN_WIDTH/2)
- scroll.x = width - SCREEN_WIDTH/2;
- if(scroll.y < -SCREEN_HEIGHT/2)
- scroll.y = -SCREEN_HEIGHT/2;
- if(scroll.y > height - SCREEN_HEIGHT/2)
- scroll.y = height - SCREEN_HEIGHT/2;
-
- // set camera translation, since BadGuys like it
- sector->camera->set_scrolling((int)scroll.x, (int)scroll.y);
-
- if(left_button && mouse_moved)
- for(unsigned int x = 0; x < selection.size(); x++)
- for(unsigned int y = 0; y < selection[x].size(); y++)
- change((int)(scroll.x + mouse_x) + (x*32),
- (int)(scroll.y + mouse_y) + (y*32), selection[x][y],
- cur_layer);
- }
-}
-
-#define FADING_TIME .6
-
-void LevelEditor::draw(DrawingContext& context)
-{
- context.draw_text(white_text, _("Level Editor"), Vector(10, 5), LEFT_ALLIGN, LAYER_GUI);
- mouse_cursor->draw(context);
-
- // draw a filled background
- context.draw_filled_rect(Vector(0,0), Vector(SCREEN_WIDTH,SCREEN_HEIGHT), Color(60,60,60), LAYER_BACKGROUND0-1);
-
- if(level_name_timer.check())
- {
- context.push_transform();
- if(level_name_timer.get_timeleft() < FADING_TIME)
- context.set_alpha(int(level_name_timer.get_timeleft() * 255 / FADING_TIME));
-
- context.draw_text(gold_text, level->name, Vector(SCREEN_WIDTH/2, 30), CENTER_ALLIGN, LAYER_GUI);
- if(level_nb != -1)
- {
- char str[128];
- sprintf(str, "%i/%i", level_nb+1, level_subset->get_num_levels());
- context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2, 50), CENTER_ALLIGN, LAYER_GUI);
- }
-
- context.pop_transform();
- }
- if(sector)
- context.draw_text(white_small_text, _("F1 for help"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10);
- else
- context.draw_text(white_small_text, _("Choose a level subset"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10);
-
- Menu* menu = Menu::current();
- if(menu)
- menu->draw(context);
- else
- {
- tiles_board->draw(context);
- tiles_layer->draw(context);
- level_options->draw(context);
- }
-
- // draw selection
- if(sector)
- {
- if(!middle_button)
- {
- context.set_drawing_effect(SEMI_TRANSPARENT);
-
- if(selection.size())
- {
- if(selection[0][0] == 0 && selection.size() == 1)
- context.draw_surface(img_rubber_bt, Vector(mouse_x - 8,
- mouse_y - 8), LAYER_GUI-2);
- else if(selection[0][0] >= gameobjs_first_id || selection[0][0] < 0)
- {
- // FIXME: this should draw an object image near cursor
- #if 0
- int id = selection[0][0];
-
- if(id == OBJ_TRAMPOLINE)
- context.draw_surface(img_trampoline[0].get_frame(0), Vector(mouse_x - 8,
- mouse_y - 8), LAYER_GUI-2);
- else if(id == OBJ_FLYING_PLATFORM)
- context.draw_surface(img_flying_platform->get_frame(0), Vector(mouse_x - 8,
- mouse_y - 8), LAYER_GUI-2);
- else
- if(id == OBJ_DOOR)
- /*context.draw_surface(door->get_frame(0), Vector(mouse_x - 8,
- mouse_y - 8), LAYER_GUI-2);*/
- ;
- else
- {
- BadGuyKind kind = BadGuyKind((-id)-1);
- BadGuy badguy(kind, 0,0);
- badguy.activate(LEFT);
- Surface *img = badguy.get_image();
-
- context.draw_surface(img, Vector(mouse_x - 8,
- mouse_y - 8), LAYER_GUI-2);
- }
- #endif
- }
- else
- {
- for(unsigned int x = 0; x < selection.size(); x++)
- for(unsigned int y = 0; y < selection[x].size(); y++) {
- const Tile* tile = tile_manager->get(selection[x][y]);
- tile->draw(context,
- Vector(mouse_x + x*32 - 8, mouse_y + y*32 - 8),
- LAYER_GUI-2);
- }
- }
- }
- context.set_drawing_effect(NONE_EFFECT);
- }
- else
- context.draw_filled_rect(Vector(std::min((int)selection_ini.x, mouse_x)*zoom,
- std::min((int)selection_ini.y, mouse_y))*zoom,
- Vector(abs(mouse_x - (int)selection_ini.x)*zoom,
- abs(mouse_y - (int)selection_ini.y)*zoom),
- Color(170,255,170,128), LAYER_GUI-2);
-
- if(show_grid)
- {
- for(int x = 0; x < SCREEN_WIDTH / (32*zoom); x++)
- {
- int pos = (int)(x*32*zoom) - ((int)scroll.x % 32);
- context.draw_filled_rect(Vector (pos, 0), Vector(1, SCREEN_HEIGHT),
- Color(225, 225, 225), LAYER_GUI-50);
- }
- for(int y = 0; y < SCREEN_HEIGHT / (32*zoom); y++)
- {
- int pos = (int)(y*32*zoom) - ((int)scroll.y % 32);
- context.draw_filled_rect(Vector (0, pos), Vector(SCREEN_WIDTH, 1),
- Color(225, 225, 225), LAYER_GUI-50);
- }
- }
-
- context.push_transform();
- context.set_translation(scroll);
- context.set_zooming(zoom);
-
- for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i)
- {
- TileMap* tilemap = dynamic_cast<TileMap*> (*i);
- if(tilemap)
- { // draw the non-selected tiles semi-transparently
- context.push_transform();
-
- if(tilemap->get_layer() != cur_layer)
- context.set_drawing_effect(SEMI_TRANSPARENT);
- (*i)->draw(context);
-
- context.pop_transform();
- continue;
- }
- Background* background = dynamic_cast<Background*> (*i);
- if(background)
- { // don't resize background
- context.push_transform();
- context.set_zooming(1.0);
- (*i)->draw(context);
- context.pop_transform();
- }
- else
- (*i)->draw(context);
- }
-
- context.pop_transform();
- }
- else
- context.draw_filled_rect(Vector(0,0), Vector(SCREEN_WIDTH,SCREEN_HEIGHT),Color(0,0,0), LAYER_BACKGROUND0);
-
- context.do_drawing();
-}
-
-void LevelEditor::load_level_subset(std::string filename)
-{
- delete level_subset;
- level_subset = new LevelSubset();
- level_subset->load(filename.c_str());
- load_level(0);
-}
-
-void LevelEditor::load_level(std::string filename)
-{
- if(level_changed)
- {
- if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
- save_level();
- else
- return;
- }
-
- level_filename = filename;
-
- delete level;
- level = new Level();
- level->load(filename);
-
- sectornum = 0;
- load_sector(0);
- level_name_timer.start(3000);
- scroll.x = scroll.y = 0;
- level_changed = false;
-
- settings_menu->get_item_by_id(MN_ID_NAME).change_input(level->name.c_str());
- settings_menu->get_item_by_id(MN_ID_AUTHOR).change_input(level->author.c_str());
-}
-
-void LevelEditor::load_level(int nb)
-{
- if(level_changed)
- {
- if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
- save_level();
- else
- return;
- }
-
- level_nb = nb;
- level_filename = level_subset->get_level_filename(level_nb);
-
- load_level(level_filename);
-}
-
-void LevelEditor::load_sector(size_t num)
-{
- assert(num <= level->get_sector_count());
-
- if(num >= level->get_sector_count())
- {
- if(!confirm_dialog(NULL, _("No more sectors exist. Create another?")))
- return;
- Sector* sector_ = create_sector("new_sector",25,19);
- level->add_sector(sector_);
- num = level->get_sector_count()-1;
- }
-
- sector = level->get_sector(num);
-
- /* Load sector stuff */
-
- sector->update_game_objects();
-
- foregrounds = solids = backgrounds = 0;
- /* Point foregrounds, backgrounds, solids to its layer */
- for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); i++)
- {
- TileMap* tilemap = dynamic_cast<TileMap*> (*i);
- if(tilemap)
- {
- if(tilemap->get_layer() == LAYER_FOREGROUNDTILES)
- foregrounds = tilemap;
- else if(tilemap->get_layer() == LAYER_TILES)
- solids = tilemap;
- else if(tilemap->get_layer() == LAYER_BACKGROUNDTILES)
- backgrounds = tilemap;
- }
- }
-
- if(!foregrounds)
- {
- TileMap* tilemap = new TileMap(LAYER_FOREGROUNDTILES, false, solids->get_width(), solids->get_height());
- sector->add_object(tilemap);
- sector->update_game_objects();
- }
- if(!backgrounds)
- {
- TileMap* tilemap = new TileMap(LAYER_BACKGROUNDTILES, false, solids->get_width(), solids->get_height());
- sector->add_object(tilemap);
- sector->update_game_objects();
- }
-
- char str[64];
- sprintf(str, "%i", solids->get_width());
- settings_menu->get_item_by_id(MN_ID_WIDTH).change_input(str);
- sprintf(str, "%i", solids->get_height());
- settings_menu->get_item_by_id(MN_ID_HEIGHT).change_input(str);
-
- sectornum = num;
-}
-
-void LevelEditor::save_level()
-{
- level->save(level_filename);
- level_changed = false;
-}
-
-void LevelEditor::test_level()
-{
- if(level_changed) {
- if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
- save_level();
- else
- return;
- }
-
- GameSession session(level_filename, ST_GL_TEST);
- session.run();
- // player_status.reset();
- sound_manager->halt_music();
-}
-
-void LevelEditor::change(int x, int y, int newtile, int layer)
-{
- (void) layer;
- // find the tilemap of the current layer, and then change the tile
- if(x < 0 || (unsigned int)x >= sector->solids->get_width()*32 ||
- y < 0 || (unsigned int)y >= sector->solids->get_height()*32)
- return;
-
- level_changed = true;
-
- if(zoom != 1)
- {
- // no need to do this for normal view (no zoom)
- x = (int)(x * (zoom*32) / 32);
- y = (int)(y * (zoom*32) / 32);
- }
-
- if(newtile >= gameobjs_first_id) // add object
- {
- // remove an active tile or object that might be there
- change(x, y, 0, LAYER_TILES);
-
- int id = 0;
- GameObject* object = 0;
- for(Factories::iterator i = object_factories->begin(); i !=
- object_factories->end(); ++i) {
- if(id == newtile - gameobjs_first_id) {
- object = create_object(i->first, Vector(x, y));
- break;
- }
- id++;
- }
- if(object) {
- sector->add_object(object);
- sector->update_game_objects();
- }
- } else if(cur_layer == LAYER_FOREGROUNDTILES) {
- foregrounds->change(x/32, y/32, newtile);
- } else if(cur_layer == LAYER_TILES) {
- // remove a bad guy if it's there
- // we /32 in order to round numbers
- for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
- i < sector->gameobjects.end(); i++) {
-// FIXME: if there is a game objs in here, remove it!
-#if 0
- BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
- if(badguy)
- if((int)badguy->base.x/32 == x/32 && (int)badguy->base.y/32 == y/32)
- sector->gameobjects.erase(i);
- Trampoline* trampoline = dynamic_cast<Trampoline*> (*i);
- if(trampoline)
- {
- if((int)trampoline->base.x/32 == x/32 && (int)trampoline->base.y/32 == y/32)
- sector->gameobjects.erase(i);
- }
- FlyingPlatform* flying_platform = dynamic_cast<FlyingPlatform*> (*i);
- if(flying_platform)
- if((int)flying_platform->base.x/32 == x/32 && (int)flying_platform->base.y/32 == y/32)
- sector->gameobjects.erase(i);
- Door* door = dynamic_cast<Door*> (*i);
- if(door)
- if((int)door->get_area().x/32 == x/32 && (int)door->get_area().y/32 == y/32)
- sector->gameobjects.erase(i);
-#endif
- }
- sector->update_game_objects();
- solids->change(x/32, y/32, newtile);
- } else if(cur_layer == LAYER_BACKGROUNDTILES)
- backgrounds->change(x/32, y/32, newtile);
-}
-
-void LevelEditor::show_help()
-{
- DrawingContext context;
-
- bool show_grid_t = show_grid;
- show_grid = false;
- mouse_cursor->set_state(MC_HIDE);
-
-
- char str[1024];
- const char *text1[] = {
- _("This is the built-in level editor. Its aim is to be intuitive\n"
- "and simple to use, so it should be pretty straightforward.\n"
- "\n"
- "To open a level, first you'll have to select a level subset from\n"
- "the menu (or create your own).\n"
- "A level subset is basically a collection of levels.\n"
- "They can then be played from the Contrib menu.\n"
- "\n"
- "To access the menu from the level editor, just press Esc.\n"
- "\n"
- "You are currently looking at the level. To scroll it, just\n"
- "press the right mouse button and drag the mouse. It will move like\n"
- "a strategy game.\n"
- "You can also use the arrow keys and Page Up/Down.\n"
- "\n"
- "'+' and '-' keys can be used to zoom the level in/out.\n"
- "\n"
- "You probably already noticed those floating groups of buttons.\n"
- "Each one serves a different purpose. To select a certain button\n"
- "just press the Left mouse button on it. A few buttons have key\n"
- "shortcuts. You can find them by pressing the Right mouse button on\n"
- "a button. That will also show what that button does.\n"
- "Groups of buttons can also be moved around by just dragging them,\n"
- "while pressing the Left mouse button.\n"
- "\n"
- "Let's learn a bit of what each group of buttons does, shall we?\n"
- "\n"
- "To starting putting tiles and objects around use the bigger group\n"
- "of buttons. Each button is a different tile. To put it on the level,\n"
- "just press it and then left click in the level.\n"
- "You can also copy tiles from the level by using the middle mouse button.\n"
- "Use the mouse wheel to scroll that group of buttons. You will find\n"
- "enemies and game objects in the bottom.\n")
- };
-
- const char *text2[] = {
- _("The Foreground/Interactive/Background buttons may be used to\n"
- "see and edit the respective layer. Levels have three tiles layers:\n"
- "Foreground - tiles are drawn on top of everything and have no contact\n"
- "with the player.\n"
- "Interactive - these are the tiles that have contact with the player.\n"
- "Background - tiles are drawn underneath everything and have no contact\n"
- "with the player.\n"
- "The unselected layers will be drawn semi-transparently.\n"
- "\n"
- "Last, but not least, the group of buttons that's left serves\n"
- "to do related actions with the level.\n"
- "From left to right:\n"
- "Mini arrows - can be used to choose other sectors.\n"
- "Sectors are mini-levels, so to speak, that can be accessed using a door.\n"
- "Big arrows - choose other level in the same level subset.\n"
- "Diskette - save the level\n"
- "Tux - test the level\n"
- "Tools - set a few settings for the level, including resizing it.\n"
- "\n"
- "We have reached the end of this Howto.\n"
- "\n"
- "Don't forget to send us a few cool levels. :)\n"
- "\n"
- "Enjoy,\n"
- " SuperTux development team\n"
- "\n"
- "PS: If you are looking for something more powerful, you might like to\n"
- "try FlexLay. FlexLay is a level editor that supports several games,\n"
- "including SuperTux. It is an independent project.\n"
- "Webpage: http://pingus.seul.org/~grumbel/flexlay/")
- };
-
- const char **text[] = { text1, text2 };
-
-
- bool done;
- for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++)
- {
- draw(context);
-
- context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(SCREEN_WIDTH/2, 60), CENTER_ALLIGN, LAYER_GUI);
-
- context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI);
-
- sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0]));
- context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT-60), CENTER_ALLIGN, LAYER_GUI);
-
- context.do_drawing();
-
- done = false;
-
- while(!done) {
- SDL_Event event;
- done = wait_for_event(event);
- SDL_Delay(50);
- }
- }
-
- show_grid = show_grid_t;
- mouse_cursor->set_state(MC_NORMAL);
-}
-
-Sector*
-LevelEditor::create_sector(const std::string& name, size_t width, size_t height)
-{
- Sector* sector = new Sector;
- sector->set_name(name);
-
- sector->add_object(new TileMap(LAYER_BACKGROUNDTILES, false, width, height));
- sector->add_object(new TileMap(LAYER_TILES, true, width, height));
- sector->add_object(new TileMap(LAYER_FOREGROUNDTILES, false, width, height));
- sector->add_object(new Camera(sector));
- sector->update_game_objects();
-
- return sector;
-}
-
-#endif
+++ /dev/null
-// $Id$
-//
-// SuperTux
-// Copyright (C) 2005 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 SUPERTUX_LEVELEDITOR_H
-#define SUPERTUX_LEVELEDITOR_H
-
-#if 0
-
-#include <set>
-#include <string>
-
-#include "video/drawing_context.h"
-#include "timer.h"
-#include "level.h"
-#include "level_subset.h"
-
-using namespace SuperTux;
-
-namespace SuperTux {
-class ButtonGroup;
-}
-
-class Menu;
-class Sector;
-class TileMap;
-class Surface;
-
-enum {
- MN_ID_RETURN,
- MN_ID_LOAD_SUBSET,
- MN_ID_QUIT,
-
- // settings menu ids:
- MN_ID_NAME,
- MN_ID_AUTHOR,
- MN_ID_WIDTH,
- MN_ID_HEIGHT,
- MN_ID_APPLY_SETTINGS,
-
- // creating subset menu ids:
- MN_ID_FILENAME_SUBSET,
- MN_ID_TITLE_SUBSET,
- MN_ID_DESCRIPTION_SUBSET,
- MN_ID_CREATE_SUBSET
- };
-
-enum {
- BT_LEVEL_SAVE,
- BT_LEVEL_TEST,
- BT_LEVEL_SETUP,
-
- BT_NEXT_LEVEL,
- BT_PREVIOUS_LEVEL,
- BT_NEXT_SECTOR,
- BT_PREVIOUS_SECTOR
- };
-
-enum {
- OBJ_TRAMPOLINE = -100,
- OBJ_FLYING_PLATFORM = -101,
- OBJ_DOOR = -102
- };
-
-class LevelEditor
-{
-public:
- LevelEditor();
- ~LevelEditor();
-
- void run(const std::string filename = "");
-
-private:
- void events();
- void action();
- void draw(DrawingContext& context);
-
- void load_level_subset(std::string filename);
- void load_level(std::string filename);
- void load_level(int nb);
- void load_sector(size_t num);
-
- void save_level();
- void test_level();
- void setup_level();
-
- void show_help();
-
- void change(int x, int y, int newtile, int layer);
-
- void load_buttons_gfx();
- void free_buttons_gfx();
-
- Level* level;
- std::string level_filename;
-
- size_t sectornum; // number of current sector
- Sector* sector; // current sector
- TileMap *solids, *foregrounds, *backgrounds;
- std::string sector_name;
-
- std::set<std::string> level_subsets;
- LevelSubset* level_subset;
- int level_nb;
-
- Menu* main_menu;
- Menu* subset_menu;
- Menu* create_subset_menu;
- Menu* settings_menu;
-
- bool left_button, middle_button, mouse_moved;
- int mouse_x, mouse_y;
- bool done;
- bool show_grid;
-
- Vector scroll;
- float zoom;
-
- Timer level_name_timer;
-
- Surface *img_background_bt, *img_foreground_bt, *img_interactive_bt;
- Surface *img_save_level_bt, *img_setup_level_bt, *img_test_level_bt;
- Surface *img_rubber_bt;
- Surface *img_previous_level_bt, *img_next_level_bt, *img_previous_sector_bt, *img_next_sector_bt;
-
- ButtonGroup *tiles_board, *tiles_layer, *level_options;
- int gameobjs_first_id, cur_layer;
-
- std::vector <std::vector <int> > selection;
- Vector selection_ini, selection_end;
-
- bool level_changed;
-
-private:
- Sector* create_sector(const std::string& name, size_t width, size_t height);
-};
-
-#endif
-
-#endif
{
sound_manager = new SoundManager();
- int format = MIX_DEFAULT_FORMAT;
- if(Mix_OpenAudio(config->audio_frequency, format, config->audio_channels,
- config->audio_chunksize) < 0) {
- std::cerr << "Couldn't initialize audio ("
- << config->audio_frequency << "HZ, " << config->audio_channels
- << " Channels, Format " << format << ", ChunkSize "
- << config->audio_chunksize << "): " << SDL_GetError() << "\n";
- return;
- }
- sound_manager->set_audio_device_available(true);
sound_manager->enable_sound(config->sound_enabled);
sound_manager->enable_music(config->music_enabled);
-
- if(Mix_AllocateChannels(config->audio_voices) < 0) {
- std::cerr << "Couldn't allocate '" << config->audio_voices << "' audio voices: "
- << SDL_GetError() << "\n";
- return;
- }
}
static void quit_audio()
{
if(sound_manager) {
- if(sound_manager->audio_device_available())
- Mix_CloseAudio();
-
delete sound_manager;
sound_manager = 0;
}
}
if(SDL_GetTicks() - ticks >= (max - min))
running = false;
+ sound_manager->update();
SDL_Delay(10);
}
}
#include "game_session.h"
#include "gui/menu.h"
#include "gui/button.h"
+#include "audio/sound_manager.h"
#include "title.h"
#include "resources.h"
#include "worldmap.h"
#include <config.h>
#include <math.h>
+#include <stdexcept>
#include "ambient_sound.h"
#include "object_factory.h"
#include "lisp/lisp.h"
#include "sector.h"
+#include "audio/sound_manager.h"
+#include "audio/sound_source.h"
AmbientSound::AmbientSound(const lisp::Lisp& lisp)
{
-
position.x=0;
position.y=0;
lisp.get("silence_distance",silence_distance);
- playing=-1; // not playing at the beginning
+ sound_source = 0; // not playing at the beginning
latency=0;
}
AmbientSound::AmbientSound(Vector pos, float factor, float bias, float vol, std::string file)
{
-
position.x=pos.x;
position.y=pos.y;
else
silence_distance = 1/distance_factor;
- playing=-1; // not playing at the beginning
+ sound_source = 0; // not playing at the beginning
latency=0;
}
void
AmbientSound::stop_playing() {
- if (playing>=0) {
- Mix_HaltChannel(playing);
- playing=-1;
- }
+ delete sound_source;
+ sound_source = 0;
}
void
AmbientSound::start_playing()
{
- playing=sound_manager->play_sound(sample,-1);
- Mix_Volume(playing,0);
- currentvolume=targetvolume=1e-20;
+ try {
+ std::string filename = "sounds/";
+ filename += sample;
+ filename += ".wav";
+ sound_source = sound_manager->create_sound_source(filename);
+ if(!sound_source)
+ throw std::runtime_error("file not found");
+
+ sound_source->set_gain(0);
+ sound_source->set_looping(true);
+ currentvolume=targetvolume=1e-20;
+ sound_source->play();
+ } catch(std::exception& e) {
+ std::cerr << "Couldn't play '" << sample << "': " << e.what() << "\n";
+ delete sound_source;
+ sound_source = 0;
+ }
}
void
currentvolume*=pow(rise,deltat*10);
currentvolume += 1e-6; // volume is at least 1e-6 (0 would never rise)
- if (playing>=0) {
+ if (sound_source != 0) {
// set the volume
- Mix_Volume(playing,(int)(currentvolume*maximumvolume*MIX_MAX_VOLUME));
+ sound_source->set_gain(currentvolume*maximumvolume);
if (sqrdistance>=silence_distance && currentvolume<1e-3)
stop_playing();
#ifndef __AMBIENT_SOUND_H__
#define __AMBIENT_SOUND_H__
-
#include "game_object.h"
#include "resources.h"
#include "player.h"
#include "SDL_mixer.h"
+class SoundSource;
+
class AmbientSound : public GameObject
{
public:
Vector dimension;
std::string sample;
- int playing;
+ SoundSource* sound_source;
int latency;
float distance_factor; /// distance scaling
BonusBlock::try_open()
{
if(sprite->get_action_name() == "empty") {
- sound_manager->play_sound("brick");
+ sound_manager->play("brick");
return;
}
get_pos(), new Flower(Flower::FIREFLOWER));
sector->add_object(riser);
}
- sound_manager->play_sound("upgrade");
+ sound_manager->play("upgrade");
break;
case CONTENT_ICEGROW:
get_pos(), new Flower(Flower::ICEFLOWER));
sector->add_object(riser);
}
- sound_manager->play_sound("upgrade");
+ sound_manager->play("upgrade");
break;
case CONTENT_STAR:
SpecialRiser* riser = new SpecialRiser(get_pos(), object);
object = 0;
sector->add_object(riser);
- sound_manager->play_sound("upgrade");
+ sound_manager->play("upgrade");
break;
//default:
if(sprite->get_action_name() == "empty")
return;
- sound_manager->play_sound("brick");
+ sound_manager->play("brick");
Sector* sector = Sector::current();
Player& player = *(sector->player);
if(coin_counter > 0) {
sector->add_object(new Particles(pos, 0, 360, Vector(140, 140),
Vector(0, 0), 45, Color(red, green, 0), 3, 1.3,
LAYER_FOREGROUND1+1));
- sound_manager->play_sound("fireworks");
+ sound_manager->play("fireworks");
timer.start(((float) rand() / RAND_MAX) + .5);
}
}
#include "camera.h"
#include "sector.h"
#include "player.h"
+#include "audio/sound_manager.h"
#include "sprite/sprite_manager.h"
Flower::Flower(Type _type)
else
player->set_bonus(ICE_BONUS, true);
- sound_manager->play_sound("fire-flower");
+ sound_manager->play("fire-flower");
remove_me();
return ABORT_MOVE;
}
#include "camera.h"
#include "sector.h"
#include "player.h"
+#include "audio/sound_manager.h"
#include "sprite/sprite_manager.h"
GrowUp::GrowUp()
Player* player = dynamic_cast<Player*>(&other);
if(player != 0) {
player->set_bonus(GROWUP_BONUS, true);
- sound_manager->play_sound("grow");
+ sound_manager->play("grow");
remove_me();
return ABORT_MOVE;
#include "sprite/sprite.h"
#include "sprite/sprite_manager.h"
#include "video/drawing_context.h"
+#include "audio/sound_manager.h"
#include "object_factory.h"
InvisibleBlock::InvisibleBlock(const Vector& pos)
return;
sprite->set_action("empty");
- sound_manager->play_sound("brick");
+ sound_manager->play("brick");
start_bounce();
flags |= FLAG_SOLID;
visible = true;
#include "gettext.h"
#include "sprite/sprite_manager.h"
+#include "audio/sound_manager.h"
#include "player.h"
#include "tile.h"
#include "sprite/sprite.h"
// let's skid!
if(fabs(vx)>SKID_XM && !skidding_timer.started()) {
skidding_timer.start(SKID_TIME);
- sound_manager->play_sound("skid");
+ sound_manager->play("skid");
// dust some partcles
Sector::current()->add_object(
new Particles(
can_flap = false;
flaps_nb = 0; // Ricardo's flapping
if (is_big())
- sound_manager->play_sound("bigjump");
+ sound_manager->play("bigjump");
else
- sound_manager->play_sound("jump");
+ sound_manager->play("jump");
} else if(!controller->hold(Controller::JUMP)) { // Let go of jump key
if (!flapping && !duck && !falling_from_flap && !on_ground()) {
can_flap = true;
void
Player::make_invincible()
{
- sound_manager->play_sound("invincible");
+ sound_manager->play("invincible");
invincible_timer.start(TUX_INVINCIBLE_TIME);
Sector::current()->play_music(HERRING_MUSIC);
}
safe_timer.get_timeleft() > 0 || invincible_timer.get_timeleft() > 0)
return;
- sound_manager->play_sound("hurt");
+ sound_manager->play("hurt");
physic.set_velocity_x(0);
class Portable;
/* Times: */
-static const float TUX_SAFE_TIME = 1.250;
+static const float TUX_SAFE_TIME = 1.8;
static const float TUX_INVINCIBLE_TIME = 10.0;
static const float TUX_INVINCIBLE_TIME_WARNING = 2.0;
static const float TUX_FLAPPING_TIME = 1; /* How long Tux can flap his wings to gain additional jump height */
#include "resources.h"
#include "player.h"
#include "sprite/sprite_manager.h"
+#include "audio/sound_manager.h"
#include "object_factory.h"
#include "sector.h"
#include "scripting/script_interpreter.h"
// some defaults if no script has been set
if (sprite->get_name() == "egg") {
player->set_bonus(GROWUP_BONUS, true);
- sound_manager->play_sound("grow");
+ sound_manager->play("grow");
} else if (sprite->get_name() == "fireflower") {
player->set_bonus(FIRE_BONUS, true);
- sound_manager->play_sound("fire-flower");
+ sound_manager->play("fire-flower");
} else if (sprite->get_name() == "star") {
player->make_invincible();
} else if (sprite->get_name() == "1up") {
#include "physfs_stream.h"
+#include <assert.h>
#include <physfs.h>
#include <stdexcept>
#include <sstream>
int
IFileStreambuf::underflow()
{
- if(PHYSFS_eof(file))
+ if(PHYSFS_eof(file)) {
return traits_type::eof();
-
- size_t bytesread = (size_t) PHYSFS_read(file, buf, 1, sizeof(buf));
- if(bytesread == 0)
+ }
+
+ PHYSFS_sint64 bytesread = (size_t) PHYSFS_read(file, buf, 1, sizeof(buf));
+ if(bytesread <= 0) {
return traits_type::eof();
+ }
setg(buf, buf, buf + bytesread);
return buf[0];
}
+IFileStreambuf::pos_type
+IFileStreambuf::seekpos(pos_type pos, std::ios_base::openmode)
+{
+ if(PHYSFS_seek(file, static_cast<PHYSFS_uint64> (pos)) == 0) {
+ return pos_type(off_type(-1));
+ }
+
+ // the seek invalidated the buffer
+ setg(buf, buf, buf);
+ return pos;
+}
+
+IFileStreambuf::pos_type
+IFileStreambuf::seekoff(off_type off, std::ios_base::seekdir dir,
+ std::ios_base::openmode mode)
+{
+ off_type pos = off;
+ PHYSFS_sint64 ptell = PHYSFS_tell(file);
+
+ switch(dir) {
+ case std::ios_base::beg:
+ break;
+ case std::ios_base::cur:
+ if(off == 0)
+ return static_cast<pos_type> (ptell) - static_cast<pos_type> (egptr() - gptr());
+ pos += static_cast<off_type> (ptell) - static_cast<off_type> (egptr() - gptr());
+ break;
+ case std::ios_base::end:
+ pos += static_cast<off_type> (PHYSFS_fileLength(file));
+ break;
+ default:
+#ifdef DEBUG
+ assert(false);
+#else
+ return pos_type(off_type(-1));
+#endif
+ }
+
+ return seekpos(static_cast<pos_type> (pos), mode);
+}
+
//---------------------------------------------------------------------------
OFileStreambuf::OFileStreambuf(const std::string& filename)
protected:
virtual int underflow();
+ virtual pos_type seekoff(off_type pos, std::ios_base::seekdir,
+ std::ios_base::openmode);
+ virtual pos_type seekpos(pos_type pos, std::ios_base::openmode);
private:
PHYSFS_file* file;
#include "resources.h"
#include "gettext.h"
#include "video/drawing_context.h"
+#include "audio/sound_manager.h"
#include "main.h"
static const int START_LIVES = 4;
{
if(lives < MAX_LIVES)
++lives;
- sound_manager->play_sound("lifeup");
+ sound_manager->play("lifeup");
}
void
incLives();
coins = 0;
}
- sound_manager->play_sound("coin");
+ sound_manager->play("coin");
}
void
#include "object/gameobjs.h"
#include "object/player.h"
-MusicRef herring_song;
-MusicRef level_end_song;
-MusicRef credits_song;
-
SpriteManager* sprite_manager = 0;
TileManager* tile_manager = 0;
SoundManager* sound_manager = 0;
/* Tux life: */
tux_life = new Surface("images/creatures/tux_small/tux-life.png", true);
+#if 0
/* Sound effects: */
sound_manager->preload_sound("jump");
sound_manager->preload_sound("bigjump");
sound_manager->preload_sound("explosion");
sound_manager->preload_sound("warp");
sound_manager->preload_sound("fireworks");
-
- /* Herring song */
- herring_song = sound_manager->load_music("music/salcon.mod");
- level_end_song = sound_manager->load_music("music/leveldone.mod");
+#endif
}
/* Free shared data: */
#define SUPERTUX_RESOURCES_H
#include <string>
-#include "audio/musicref.h"
class SpriteManager;
class Menu;
extern Surface* img_super_bkgd;
extern Surface* tux_life;
-extern MusicRef herring_song;
-extern MusicRef level_end_song;
-
extern SpriteManager* sprite_manager;
extern TileManager* tile_manager;
extern SoundManager* sound_manager;
#include "resources.h"
#include "audio/sound_manager.h"
-#define NOIMPL printf("%s not implemented.\n", __PRETTY_FUNCTION__);
-
namespace Scripting
{
{}
void
- Sound::play_music(const std::string& )
+ Sound::play_music(const std::string& name)
{
- NOIMPL;
+ std::string filename = "music/";
+ filename += name;
+ filename += ".ogg";
+ sound_manager->play_music(name);
}
void
- Sound::play_sound(const std::string& name)
+ Sound::play(const std::string& name)
{
- sound_manager->play_sound(name);
+ sound_manager->play(name);
}
}
/**
* Play a sound effect. The name should be without path or .wav extension
*/
- void play_sound(const std::string& soundfile);
+ void play(const std::string& soundfile);
#ifndef SCRIPTING_API
Sound();
return 0;
}
-static int Sound_play_sound_wrapper(HSQUIRRELVM v)
+static int Sound_play_wrapper(HSQUIRRELVM v)
{
Scripting::Sound* _this;
sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
const char* arg0;
sq_getstring(v, 2, &arg0);
- _this->play_sound(arg0);
+ _this->play(arg0);
return 0;
}
static WrappedFunction supertux_Sound_methods[] = {
{ "play_music", &Sound_play_music_wrapper },
- { "play_sound", &Sound_play_sound_wrapper },
+ { "play", &Sound_play_wrapper },
};
static WrappedFunction supertux_Text_methods[] = {
iter.value()->get(gravity);
} else if(token == "music") {
iter.value()->get(song_title);
- load_music();
} else if(token == "spawnpoint") {
SpawnPoint* sp = new SpawnPoint(iter.lisp());
spawnpoints.push_back(sp);
song_title = "Mortimers_chipdisko.mod";
reader.get("music", song_title);
- load_music();
int width, height = 15;
reader.get("width", width);
}
add_object(new_bullet);
- sound_manager->play_sound("shoot");
+ sound_manager->play("shoot");
return true;
}
}
void
-Sector::load_music()
-{
- level_song = sound_manager->load_music("/music/" + song_title);
-}
-
-void
Sector::play_music(MusicType type)
{
currentmusic = type;
switch(currentmusic) {
case LEVEL_MUSIC:
- sound_manager->play_music(level_song);
+ sound_manager->play_music(std::string("music/") + song_title);
break;
case HERRING_MUSIC:
- sound_manager->play_music(herring_song);
+ sound_manager->play_music("music/salcon.mod");
break;
default:
- sound_manager->halt_music();
+ sound_manager->play_music("");
break;
}
}
#include "direction.h"
#include "math/vector.h"
-#include "audio/musicref.h"
#include "video/drawing_context.h"
namespace lisp {
class CollisionGrid;
class ScriptInterpreter;
class SpawnPoint;
+class MovingObject;
enum MusicType {
LEVEL_MUSIC,
private:
void collision_object(MovingObject* object1, MovingObject* object2);
- void load_music();
GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp);
static Sector* _current;
std::string name;
- MusicRef level_song;
-
public:
std::string song_title;
float gravity;
#include "video/drawing_context.h"
#include "lisp/parser.h"
#include "lisp/lisp.h"
+#include "audio/sound_manager.h"
#include "main.h"
#include "control/joystickkeyboardcontroller.h"
}
context.do_drawing();
+ sound_manager->update();
if(SCREEN_HEIGHT+y-scroll < 0 && 20+SCREEN_HEIGHT+y-scroll < 0)
done = 1;
#include "title.h"
#include "video/screen.h"
#include "video/surface.h"
+#include "audio/sound_manager.h"
#include "gui/menu.h"
#include "timer.h"
#include "lisp/lisp.h"
#include "level_subset.h"
#include "game_session.h"
#include "worldmap.h"
-#include "leveleditor.h"
#include "player_status.h"
#include "tile.h"
#include "sector.h"
{
walking = true;
//LevelEditor* leveleditor;
- MusicRef credits_music;
controller = new CodeController();
titlesession = new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME);
#endif
case MNID_CREDITS:
fadeout(500);
- credits_music = sound_manager->load_music(
- "/music/credits.ogg");
- sound_manager->play_music(credits_music);
+ sound_manager->play_music("music/credits.ogg");
display_text_file("credits.txt");
fadeout(500);
Menu::set_current(main_menu);
}
context.do_drawing();
+ sound_manager->update();
//frame_rate.update();
if (special_tile->teleport_dest != Vector(-1,-1))
{
// TODO: an animation, camera scrolling or a fading would be a nice touch
- sound_manager->play_sound("warp");
+ sound_manager->play("warp");
tux->back_direction = D_NONE;
tux->set_tile_pos(special_tile->teleport_dest);
SDL_Delay(1000);
break;
}
- sound_manager->play_music(song);
+ sound_manager->play_music(std::string("music/") + music);
Menu::set_current(0);
if (!savegame_file.empty())
savegame(savegame_file);
quit = false;
- song = sound_manager->load_music("music/" + music);
- sound_manager->play_music(song);
+ sound_manager->play_music(std::string("music/") + music);
if(!intro_displayed && intro_script != "") {
try {
context.pop_transform();
get_input();
update(elapsed_time);
+ sound_manager->update();
if(Menu::current()) {
Menu::current()->draw(context);
#include <string>
#include "math/vector.h"
-#include "audio/musicref.h"
#include "video/screen.h"
#include "lisp/lisp.h"
#include "control/controller.h"
typedef std::vector<SpawnPoint*> SpawnPoints;
SpawnPoints spawn_points;
- MusicRef song;
-
Vector offset;
std::string savegame_file;