Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

MatStorm

Frischling

  • »MatStorm« ist der Autor dieses Themas

Beiträge: 14

Beruf: Student

  • Private Nachricht senden

1

01.04.2013, 16:34

SDL_BlitSurface/Große Surfaces/Niedrige FPS

Hallo alle zusammen^^

Da das mein erster Thread hier im Forum ist, möchte ich mich erstmal vorstellen. Ich bin 18 Jahre alt und lerne seit mehren Jahren C++ (4 wenn ich mich recht erinnere, wobei es natürlich auch lustlose Phasen gab :P ). Ich habe mich demletzt mit wxWidgets sowie Netzwerkprogrammierung befasst. Nun befasse ich mich eben mit Spieleprogrammierung. Ich besitze das Buch "C++ für Spieleprogrammierer" wie auch "3D-Spieleprogrammierung mit DirectX und C++", doch da mir das alles mit 3D dann doch zu hoch ist, versuche ich verzweifelt ein gescheites 2D Spiel zusammenzubasteln, was jedoch nicht wirklich klappt :P

Das Spiel: Ich versuche ein Spiel zu proggen, bei dem es 2 Mutterschiffe gibt, unbeweglich und dient als "Hauptquatier". Dieses Mutterschiff kann 3 Arten von Schiffen erstellen. Die Karte ist mit einem "Nebel" zugedeckt. Je nach Schiff kann man den Nebel mit einem größeren Radius aufdecken. Ziel des Spiels ist es, das gegnerische Mutterschiff zu zerstören.

Der "Rahmen" in dem das Spiel läuft: Im großen und ganzen hab ich das System aus dem Buch übernommen, also die Klassen CGame, CFramework, CTimer... Gestartet wird das Spiel jedoch nicht von einer Konsole, sondern einfach von wxWidgets, wobei es einfach eine Applikation ohne Fenster ist, die alles initialisiert, auf Fehlern prüft und dann startet und bei Game.Run() dann eben stehen bleibt, was nicht weiter tragisch ist, da man eh nichts davon mitbekommt^^

Das Problem: Für den Hintergrund habe ich eine PNG Datei. Ich nutze SDL_BlitSurface um den Ausschnitt dort herauszunehmen und auf den Bildschirm zu zeichnen. Dabei sanken meine FPS (Berechnet mit 1 / Timer->GetElapsed()) von 500 auf ca 25. Nachdem ich dann eben vorher bei der Initialisierung den Background-Surface auf das selbe Format gebracht habe wie der Bildschirm, konnte ich dann doch 333 FPS erreichen. Ich hab auch noch die Einstellung hinzugefügt, dass man durch drücken von "B" den Hintergrund ein oder ausschalten kann, falls es zu viel laggt.
Das Nächste Problem war, dass ich die Schiffe mit einem Rahmen markieren wollte. Die eigentliche Auswertung erfolgt in einer Funktion: HandleMouseClick, HandleMouseMotion oder HandleMouseRelease, die in der Eventschleife aufgerufen werden. Danach wird der Rahmen, den man gezogen hat, auf eine Surface gerendert (SDL_Surface *speciallayer), und dieser wird dann bei allen Renderfunktionen noch dazugemacht. Dies drückte meine FPS aber wieder runter. Das Problem habe ich.. "gelöst" (wobei man es nicht wirklich so nennen könnte), indem ich den speciallayer einfach überspringe, wenn die Maustaste nicht gedrückt ist.
Nun kommt das größte Problem: Der Nebel. Ich hab momentan eine 10.000 x 10.000 Surface (Spielfeldgröße), der Anfangs komplett grau gezeichnet ist. Dort werden dann Alpha-Kreise gezogen, wo sich die Schiffe befinden, falls sie sich bewegen (Mir ist nichts anderes eingefallen, wie ich das machen könnte). Den nebel kann ich ja nicht Konvertieren, da der Bildschirm über keinen Alphawert verfügt. Der Nebel ist auch nicht verzichtbar, da er ein wichtiges Merkmal für das Spiel ist. Doch der Nebel drückt die FPS auf 25 runter, wenn ich dann doch etwas markiere, dann wird es noch schlimmer :wacko:


Von der Spiellogik her hab ich keine Probleme, nur die FPS bereiten mir Kopfschmerzen :/
Mithilfe von Google hab ich nur Tipps herausgefunden wie "Use HWSURFACE" oder "SDL_DOUBLEBUFF", was ich jedoch von Anfang an drin hatte :P

Ich bedanke mich im Voraus^^

Mit freundlichen Grüßen, MatStorm

------------------------------------------------------------------------------------------------
Codeausschnitte:

C-/C++-Quelltext

1
2
3
4
5
//[in CGame::Init()]//Speciallayer konfigurieren
    speciallayer = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, Framework->GetScreen()->w,Framework->GetScreen()->h, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    //Nebel konfigurieren
    fog = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, 10000, 10000, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    SDL_FillRect(fog, 0, SDL_MapRGBA(fog->format, 50, 50, 50, 255));



C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int CGame::Run()
{
    InitMotherships();

    //Spielschleife
    while(GameRun)
    {
        try
        {
            ProcessEvents();
            Framework->Update();
            Framework->Clear();
            Update();
            Render();
            Check();
            Framework->Flip();
        }
        catch(...)
        {
            return ECR_UNKNOWN;
        }
    }
    return 0;
}


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
void CGame::Render()
{
    switch(GameState)
    {
    case 0:///////////////////////////////////////////////////////////////////////////////// MENÜ
        {
        }
        break;
    case 1:///////////////////////////////////////////////////////////////////////////////// SPIEL
        {
            //Render Background
            if(RenderBackground) SDL_BlitSurface(background, 0, Framework->GetScreen(), 0);

            //Render Gegner
            emship.Render();
            for(list<Ship1>::iterator i = elist1.begin(); i != elist1.end(); i++) i->Render();
            for(list<Ship2>::iterator i = elist2.begin(); i != elist2.end(); i++) i->Render();
            for(list<Ship3>::iterator i = elist3.begin(); i != elist3.end(); i++) i->Render();

            //Rendere Nebel
            RenderFog();

            //Rendere eigene Schiffe
            mship.Render();
            for(list<Ship1>::iterator i = slist1.begin(); i != slist1.end(); i++) i->Render();
            for(list<Ship2>::iterator i = slist2.begin(); i != slist2.end(); i++) i->Render();
            for(list<Ship3>::iterator i = slist3.begin(); i != slist3.end(); i++) i->Render();

            //Render Menüleiste
            RenderMenu();
            RenderButtons();

            //Speciallayer zeichnen
            if(RendSpecLay) SDL_BlitSurface(speciallayer, 0, Framework->GetScreen(), 0);
        }
        break;
    case 2:///////////////////////////////////////////////////////////////////////////////// OPTIONEN
        {
        }
        break;
    case 3:///////////////////////////////////////////////////////////////////////////////// PAUSE
        {
            //Render Background
            if(RenderBackground) SDL_BlitSurface(background, 0, Framework->GetScreen(), 0);

            //Rendere Mutterschiffe
            mship.Render();
            emship.Render();

            //Rendere Schiffe
            for(list<Ship1>::iterator i = slist1.begin(); i != slist1.end(); i++) i->Render();
            for(list<Ship1>::iterator i = elist1.begin(); i != elist1.end(); i++) i->Render();
            for(list<Ship2>::iterator i = slist2.begin(); i != slist2.end(); i++) i->Render();
            for(list<Ship2>::iterator i = elist2.begin(); i != elist2.end(); i++) i->Render();
            for(list<Ship3>::iterator i = slist3.begin(); i != slist3.end(); i++) i->Render();
            for(list<Ship3>::iterator i = elist3.begin(); i != elist3.end(); i++) i->Render();

            //Render Menüleiste
            RenderMenu();
            RenderButtons();

            //Schwärzen und beschriften
            SDL_FillRect(speciallayer, 0, SDL_MapRGBA(speciallayer->format, 0, 0, 0, 128));
            SDL_BlitSurface(speciallayer, 0, Framework->GetScreen(), 0);
        }
        break;
    }
    RenderMouse();
    RenderFPS();
}


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
void CGame::RenderFog()
{
    SDL_Rect Rect;
    Rect.x = Welt->WorldX;
    Rect.y = Welt->WorldY;
    Rect.w = Framework->GetScreen()->w - 200;
    Rect.h = Framework->GetScreen()->h;

    SDL_BlitSurface(fog, &Rect, Framework->GetScreen(), 0);
}

MatStorm

Frischling

  • »MatStorm« ist der Autor dieses Themas

Beiträge: 14

Beruf: Student

  • Private Nachricht senden

2

02.04.2013, 21:08

Update

Ich versuche den Nebel in 1000x1000 Blöcke zu zerteilen und dadurch FPS zu gewinnen :P

Hoffe weiterhin denoch darauf, dass mir jemand erklärt, was ich hier alles Falsch gemacht habe :dash: ;(

Swoerm

Alter Hase

Beiträge: 451

Wohnort: 127.0.0.1

  • Private Nachricht senden

3

02.04.2013, 21:28

Ich versteh irgendwie nicht was du wissen willst!? ?(

C-/C++-Quelltext

1
2
    /* Keep the compiler happy */
    return(0);

MatStorm

Frischling

  • »MatStorm« ist der Autor dieses Themas

Beiträge: 14

Beruf: Student

  • Private Nachricht senden

4

02.04.2013, 21:41

Hmm und ich hab mich extra bemüht zu veruchen, mein Problem genau zu erklären x_x

Kurzfassung: Ich blitte 3 mal große Flächen, wobei 2 Alphawerte besitzen. Dadurch bekomme ich niedrige FPS und das Spiel laggt. Und ich hab keine Ahnung was ich tun soll ;(

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

5

02.04.2013, 22:30

Musst du denn unbedingt Nebel zeichnen? Ich erinnere mich wage, dass bei AOE 2 zu Anfang zumindest alles schwarz war, sprich nicht gezeichnet wurde. Das wäre am einfachsten und gleichzeitig am schnellsten.
Welche Version der SDL benutzt du überhaupt? In der neuen 2er (oder offiziell noch 1.3er) gibt es dafür RenderTexturen.
Andere Idee wäre auf OpenGL (oder direkt auf SFML) umzusteigen. Bei OpenGL wären dann Vertex Buffer Objects das Mittel der Wahl.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige