Montag, 23 Aug, 2010

Lektion 11

In dieser Lektion möchte ich euch Zeigen wie wir unserem Beispiel eine Hintergrundmusik verpassen und Sound-Effekte abspielen. Mit der Leertasten Starten oder Pausieren wir die Musik und mit L stoppen wir sie. Auf den drei Maustasten legen wie noch jeweils ein Sound-Effekt, der beim drücken der jeweiligen Taste abgespielt wird.

Als ersten brauchen wir ein paar Musikstücke, die wir uns hier besorgen:

http://www.startrekl … iles/m_theme_tng.zip
Dies wird unsere Hintergrundmusik. Entpackt das ZIP-File und benennt die Datei in title.mp3 um.

http://www.startrekl … de/clips/sound_1.wav
Das wird unser Soundeffekt für die Mittlere Maustaste. Benennt das Wave in beam.wav um.

http://www.startrekl … e/clips/sound_17.zip
Das ist der Soundeffekt für die Linke Maustaste. Entpackt die Datei und benennt sie in fire1.wav um.

http://www.startrekl … e/clips/sound_12.wav
Das wird der Soundeffekt für die Rechte Maustaste. Nennt die Datei fire2.wav.

Um einen Sound abspielen zu können benötigen wir die SDL-Mixer die wir als ersten Schritt in unser Programm einbinden.

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include <string>
#include "SDL/SDL_mixer.h"

Im nächsten Schritt erzeugen wir eine Variable die unsere Musik (Also das was im Hintergrund läuft), aufnehmen kann. Dazu nutzen wir den Typ Mix_Music.

	
//Oberflächen deklarieren
SDL_Surface* fenster = NULL;
SDL_Surface* hintergrund = NULL;
SDL_Surface* raumschiff = NULL;
SDL_Surface *text = NULL;
	
//SDL Ereignis
SDL_Event ereignis;
	
//Entält die Postitionsdaten der einzelnen Bildteile
SDL_Rect bildteil[ 4 ];
	
//Schriftart-Varibable deklarieren
TTF_Font *schriftart = NULL;
	
//Variable für Textfarbe
SDL_Color textfarbe = { 128, 88, 77 };
	
//The music that will be played
Mix_Music *title = NULL;

Dann erzeugen wir drei Variablen mit dem Typ Mix_Chunk, die unsere drei Effekte abspielen. Mit Effekten ist ein Sound gemeint der auf eine Bestimmte Aktion folgt, z.B. ein Geräusch beim Abfeuern einer Waffe.

	
//The sound effects that will be used
Mix_Chunk *fire1 = NULL;
Mix_Chunk *fire2 = NULL;
Mix_Chunk *beam = NULL;

Die erste Funktion die wir anpassen müssen ist die initalisierung. In dieser Funktion haben wir schon in der Vergangenheit sämtliche SDL-Funktionalitäten initialisiert und auch jetzt initialisieren wir hier unsere Sound-Ausgabe mit Mix_OpenAudio().

Der erste Parameter beschreibt die Sound Frequenz. Hier halten wir uns an die Empfehlungen und setzen den Wert 22050. Bei dem nächsten Parameter, dem Soundformat verhalten wir uns ähnlich und setzen diesen auf den Vorgabe-Wert MIX_DEFAULT_FORMAT. Der dritte Parameter beschreibt wie viele Kanäle wir nutzen möchten. Da wir gerne eine Stereo-Ausgabe nutzen möchten setzen wir diesen auf 2 (für Mono auf 1). Der letzte Parameter beschreibt die Sample Rate, die wir auf 4096 setzen.

void initalisierung()
{
    //Initialisieren von SDL
    SDL_Init( SDL_INIT_EVERYTHING );
	
    //TTF Funktionalitäten initalisieren
    TTF_Init();
	
    //Fenstertext
    SDL_WM_SetCaption( "SDL Mixer", NULL );
	
    //Fenster Konfigurieren
    fenster = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );
	
    //Initialize SDL_mixer
    Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 );
}

Als nächstes ändern wir die Funktion Dateien_laden. In dieser Funktion fügen wir jetzt das laden der Sound-Dateien hinzu. Mit Mix_LoadMUS() laden wir die Musik und mit Mix_LoadWAV() die Effekte.

void dateien_laden()
{
    //Hintergrund laden
    hintergrund = lade_bild( "hintergrund.png" );
	
    //Raumschiff laden
    raumschiff = lade_bild( "sprite.png" );
    //Schriftart laden
    schriftart = TTF_OpenFont( "helvetidoodlebyedt.ttf", 50 );
	
    // Musik laden
    title = Mix_LoadMUS( "title.mp3" );
	
    //Effekte laden
    fire1 = Mix_LoadWAV( "fire1.wav" );
    fire2 = Mix_LoadWAV( "fire2.wav" );
    beam = Mix_LoadWAV( "beam.wav" );
}

Nun passen wir noch unsere Aufräum-Funktion an, bevor wir uns an der Main Funktion zu schaffen machen. Mit Mix_FreeChunk() geben wir die Effekte wieder frei, mit Mix_FreeMusic() die Musik und mit Mix_CloseAudio() beenden wir das Audio-System.

void aufraeumen()
{
    //Free the sound effects
    Mix_FreeChunk( fire1 );
    Mix_FreeChunk( fire2 );
    Mix_FreeChunk( beam );
	
    //Free the sound effects
    Mix_FreeMusic( title );
	
    //SDL_mixer beenden
    Mix_CloseAudio();
	
    //Bildspeicher freigeben
    SDL_FreeSurface( hintergrund );
    SDL_FreeSurface( raumschiff );
	
    // Text freigeben
    SDL_FreeSurface( text );
	
    //Schriftart freigeben
    TTF_CloseFont( schriftart );
	
    //SDL_ttf beenden
    TTF_Quit();
    //SDL beenden
    SDL_Quit();
	
}

Als nächstes stehen die Änderungen in der Main-Funktion an. Hier haben wir nichts weiter zu tun als beim richtigen Ereignis mit Musik oder einen Effekt zu reagieren. Aus diesen Grund bleibt auch alles unverändert bis zu dem Punkt wo wir auf die Maustasten reagieren, denn hier wollen wir unsere Effekte abspielen lassen.

Einen Effekt spielen wir mit Mix_PlayChannel() ab. Der erste Parameter gibt an auf welchen Kanal der Effekt abgespielt werden soll, mit -1 sagen wir das er den ersten freien benutzen soll. Der zweite Parameter verlangt nach dem zu spielenden Effekt und der dritte Parameter gibt an wie oft der Effekt wiederholt werden soll, mit 0 wird er einmal abgespielt.

Für jede Maustaste spielen wir nun einen Effekt ab.

int main( int argc, char* args[] )
{
    int x = 250;
    int y = 250;
    char anzeige_text[20] = "Der Weltraum....";
    int ende = 0;
	
    setze_bauteil_masse();
    initalisierung();
    dateien_laden();
	
    while (ende != 1)
    {
        //Text rendern
        text = TTF_RenderText_Solid( schriftart, anzeige_text, textfarbe );
        blitten(x,y);
	
        //Anzeige aktualisieren
        SDL_Flip( fenster );
	
        while (SDL_PollEvent( &ereignis))
        {
	
            if ( ereignis.type == SDL_MOUSEBUTTONDOWN )
            {
                if ( ereignis.button.button == SDL_BUTTON_LEFT )
                {
                    sprintf(anzeige_text,"%i", ereignis.button.x);
                    Mix_PlayChannel( -1, fire1, 0 );
                }
                if ( ereignis.button.button == SDL_BUTTON_RIGHT )
                {
                    sprintf(anzeige_text,"%i", ereignis.button.y);
                    Mix_PlayChannel( -1, fire2, 0 );
                }
                if ( ereignis.button.button == SDL_BUTTON_MIDDLE )
                {
                    Mix_PlayChannel( -1, beam, 0 );
                    x = 250;
                    y = 250;
                }
            }
	

Dann geht es weiter ohne Änderungen bis das Ereignis Leertaste gedrückt eintritt.

	
            if( ereignis.type == SDL_MOUSEMOTION ) {
               x =  ereignis.button.x;
               y =  ereignis.button.y;
            }
            if ( ereignis.type == SDL_KEYDOWN )
            {
	
                switch ( ereignis.key.keysym.sym )
                {
                case SDLK_UP:
                    strcpy(anzeige_text,"Hoch");
                    break;
                case SDLK_DOWN:
                    strcpy(anzeige_text,"Unten");
                    break;
                case SDLK_LEFT:
                    strcpy(anzeige_text,"Links");
                    break;
                case SDLK_RIGHT:
                    strcpy(anzeige_text,"Rechts");
                    break;

Jetzt ist es an der Reihe das wir die Musik starten wenn die Leertaste gedrückt wird und noch keine Musik läuft (oder sich in Pause befindet) oder das wenn schon Musik läuft wir diese pausieren.

Als erstes prüfen wir ob die Musik schon läuft, auch ein Musikstück das durch Pause unterbrochen wurde, wird als “läuft gerade” betrachtet.

                case SDLK_SPACE:
                    strcpy(anzeige_text,"Der Weltraum....");
	
                    //Wurde Musik schon gespielt
                    if( Mix_PlayingMusic() == 0 ) {

Wenn kein Musikstück läuft dann starten wir es mit Mix_PlayMusic(). Der erste Parameter enthält dabei das zu spielende Musikstück und er zweite Parameter gibt an wie oft das Musikstück abgespielt werden soll. -1 ist dabei unendlich bis es manuell gestoppt wird.

                        //Musik abspielen
                        if( Mix_PlayMusic( title, -1 ) == -1 ) {
                            return 1;
                        }
                    }

Wenn ein Musikstück läuft überprüfen wir ob es in der Pause ist.

                    //Wenn Musik schon läuft
                    else {
                        //Wenn Pause
                        if( Mix_PausedMusic() == 1 ) {

Wenn ja heben wir die Pause mit Mix_ResumeMusic() auf.

                            //Weiter abspielen
                            Mix_ResumeMusic();
                        }

Wenn nicht dann pausieren wir es mit Mix_PauseMusic().

                        //Wenn die Musik schon läuft
                        else {
                            //Musik Pause
                            Mix_PauseMusic();
                        }
                    }
                    break;

An dieser Stelle stoppen wir die Musik wenn die L-Taste gedrückt wird (Die Musik kann mit der Leertaste wieder von beginnan gestartet werden).

                case SDLK_l:
                    Mix_HaltMusic();
                    strcpy(anzeige_text,"");
                    break;
                }
            }
	

Dann folgt der Rest ohne Änderung und ihr habt es geschafft :-).

            if (ereignis.type == SDL_QUIT)
            {
                ende = 1;
            }
        }
	
    }
    aufraeumen();
    return 0;
}

Den gesamten Code der Lektion 11 gibt es hier:
Lektion 11 Code

Für weiter Informationen zum SDL Mixer schaut euch das hier an:
http://jcatki.no-ip. … r/SDL_mixer_html.zip