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

1

11.02.2009, 18:55

Performance- und Anzeigeprobleme

Hallo,

ich schreib gerade für SFML eine kleine Engine bzw ein kleines Framework und hab
1. ein Performanceproblem für Tilemaps:
Das größte Tilemap ist 64x64 Felder groß - besteht also aus 4096 einzelne Sprites. Diese Sprites werden einzeln zugewiesen und gerendert.

Beim Debug Mode komm ich mit einem 64x64 Tilemap nur auf ~8 FPS
(Notebook, 2,2 GHz Dual Core, 4 GB Ram)
Beim Release komm ich zwar auf Stolze ~50 FPS aber irgendwie ist mir das immer noch zu wenig. Gibt es eine Möglichkeit die Geschwindigkeit zu verbessern?

Hier mal ein Codeauszug:

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
//////////////////////////////////////////////////////////////////////////////

// Map darstellen 64x64 Anfang

void esTilemap::ShowTilemap(int iMapArray[64][64],float fXPos, float fYPos)
{
    
    int     iSpriteNumbers  = m_iSpritesY * m_iSpritesX;                            // Gesamtanzahl aller Sprites

    int     iTilePosX       = 0;                                                    // Position X eines Tiles im Tileset

    int     iTilePosY       = 0;                                                    // Position Y eines Tiles im Tileset

    int     iSpriteNumber   = 0;                                                    // Bei welcher Sprite Nummer ist der Rendervorgang?

    int     iHeight         = 64;                                                   // Höhe des Feldes

    int     iWidth          = 64;                                                   // Breite des Feldes

    int     iZaehler        = 1;

    // To Do: Überprüfen ob ein höherer Tilewert eingegeben wurde als exisitert -> Exception !!

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


    // Leseschleife start

    for (int y = 0; y < iHeight; y++)
    {
        for (int x = 0; x < iWidth; x++)
        {
            for (int pos = 0; pos <= iSpriteNumbers; pos++)
            {
                // iMapArray auslesen

                // Werte holen

                if (pos == iMapArray[y][x])
                {
                    // Gesuchter Wert der koord Struktur entnehmen und dem SetSubRect übergeben:

                    sf::IntRect Rect(tile[pos]->iLeftKoord, tile[pos]->iTopKoord, tile[pos]->iRightKoord, tile[pos]->iBottomKoord);
        
                    // Gefundener Wert in erstes Sprite schieben

                    Sprite[iZaehler]->SetSubRect(Rect);
                    
                    iZaehler++;

                    break;
                }
            }
        }
    }
    // Leseschleife Ende


    
    float ZaehlerX = 0.0f;
    float ZaehlerY = 0.0f;

    // Renderschleife:

    for (int i = 1; i < 64*64 + 1; i++)
    {
            // Auf der X Achse verschieben bis diese zu Ende ist.

            if (ZaehlerX < iWidth)
            {
                Sprite[i]->SetPosition(m_fWidth * ZaehlerX + fXPos, m_fHeight * ZaehlerY + fYPos);
                
                ZaehlerX++;
            }
            else
            {
                ZaehlerX = 1.0f;

                // Wenn X Achse zu Ende ist auf Y Achse springen

                ZaehlerY++;
                Sprite[i]->SetPosition(0.0f + fXPos, m_fHeight * ZaehlerY + fYPos);
            }
        
        esWindow->GetApp()->Draw(*Sprite[i]);
    }
}
// Map darstellen 64x64 Ende

//////////////////////////////////////////////////////////////////////////////


Zu meinem 2. Problem:
Bei bestimmte Auflösungen (Eigentlich bei allen außer bei Fullscreen und X*600 Pixeln) wird mein Bild um 10-30 Pixel nach oben verschoben:

Bild sofort nach dem Starten des Testprogramms:

(Link)


Bild nachdem ich auf die obere Leiste Klicke und sich das Bild dem Fenster anpasst (so sollte es immer aussehen):

(Link)


Puh... das wars erstmal. Ich hoffe ihr könnt mir weiterhelfen.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

11.02.2009, 19:24

Wenn du da noch was rausholen kannst, dann musst du mal die Lib anschauen. Wenn die das nicht unterstüzt, dann gehts nicht. ;)

Du könntest natürlich immernoch selber mit OpenGL rendern dann kannst du da sicher noch mehr rausholen..

3

11.02.2009, 19:45

merkwürdiger code :lol:
wieso läufst du hier nochmal durch?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for (int pos = 0; pos <= iSpriteNumbers; pos++)
            {
                // iMapArray auslesen

                // Werte holen

                if (pos == iMapArray[y][x])
                {
                    // Gesuchter Wert der koord Struktur entnehmen und dem SetSubRect übergeben:

                    sf::IntRect Rect(tile[pos]->iLeftKoord, tile[pos]->iTopKoord, tile[pos]->iRightKoord, tile[pos]->iBottomKoord);
       
                    // Gefundener Wert in erstes Sprite schieben

                    Sprite[iZaehler]->SetSubRect(Rect);
                   
                    iZaehler++;

                    break;
                }
            }


kannst doch direkt

C-/C++-Quelltext

1
2
3
4
5
6
7
8
sf::IntRect Rect(tile[ iMapArray[y][x]]->iLeftKoord, tile[ iMapArray[y][x]]->iTopKoord, tile[ iMapArray[y][x]]->iRightKoord, tile[ iMapArray[y][x]]->iBottomKoord);
       
                    // Gefundener Wert in erstes Sprite schieben

                    Sprite[iZaehler]->SetSubRect(Rect);
                   
                    iZaehler++;

                    break;


machen?

ansonsten wäre ganz interessant, was in Sprite[] drin ist, bzw. was du da durchzählst? auch der rest deiner klasse wäre nicht schlecht.

4

11.02.2009, 20:08

Gibts bei der SFML keine Methode à la ID3DXSprite::Draw, ID3DXSprite::Flush wie bei DirectX?
fka tm

5

11.02.2009, 20:09

Die Sache ist ganz klar: Wenn du 64x64 Tiles einzelnt zeichnest und damit 4096 Drawcalls hast, dann kann die Grafikkarte und Prozessor das gar nicht packen.
Wenn du es schaffst, alles in einem DrawCall zu machen, kanns gut sein,dass du wieder 100 fps oder noch deutlich mehr hast.
Lieber dumm fragen, als dumm bleiben!

6

11.02.2009, 20:12

@ zera
weil hier die Position von jedem Sprite festgelegt wird.
Ein Arrayindex ist ein Sprite welches bestandteil von der map ist.

na dann die ganze Klasse:
(wobei ich glaub das es eine weile dauert bis mans versteht^^)
// Edit: Hier siehts schöner aus: http://rafb.net/p/HQHuwt75.html

@ TM: Wüsst ich nicht
@ Jonathan: Wie soll das gehn das ich alle in ein "Drawcall" reinpacke?! Alle einzelne Sprites zu einem Bild zusammenpacken und das dann rendern?!
Dann gibts halt ein Prooblem wenn ich ein Sprite von der Map bewegen will o.ä.

7

11.02.2009, 20:25

Wie wäre es, wenn du einfach nur die Tiles darstellst die auch auf dem Monitor angezeigt werden? Die anderen brauchste doch nicht rendern bzw. durchlaufen.

8

11.02.2009, 20:29

Naja, eine Tilemap kannst du ja als zusammenhängendes Polygongitter rendern. Dazu müssten halt sämtliche Tiles die selbe Textur benutzen, aber das kannst du ja per Texturkoordinaten lockerhinbekommen.
Und die Objekte die sich bewegen kann man dann ja noch extra Zeichnen, dürften ja deutlich weniger als 4k sein. Wenn man dann noch so 20 Stück einzelnt zeichnet,ist das kein Problem.
Wenn du aber sehr sehr viele Objekte hast, die sich bewegen, könnte Instancing eine Lösung sein.
Lieber dumm fragen, als dumm bleiben!

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

11.02.2009, 20:42

@Razor ich glaube zera hat recht. Denn überleg mal für welche pos die Bedingung erfüllt ist (genau für einen Fall und zwar pos == iMapArray[x][y])
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

10

11.02.2009, 21:06

die untere schleife

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Renderschleife:

    for (int i = 1; i < 64*64 + 1; i++)
    {
            // Auf der X Achse verschieben bis diese zu Ende ist.

            if (ZaehlerX < iWidth)
            {
                Sprite[i]->SetPosition(m_fWidth * ZaehlerX + fXPos, m_fHeight * ZaehlerY + fYPos);
               
                ZaehlerX++;
            }
            else
            {
                ZaehlerX = 1.0f;

                // Wenn X Achse zu Ende ist auf Y Achse springen

                ZaehlerY++;
                Sprite[i]->SetPosition(0.0f + fXPos, m_fHeight * ZaehlerY + fYPos);
            }
       
        esWindow->GetApp()->Draw(*Sprite[i]);
    }


lässt sich auch gut in die obere einbauen, dabei kannst du auch direkt die 4000 sprite-Instanzen sparen ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sf::Sprite dummySprite;
dummySprite.setImage(*Image);

for (int y = 0; y < iHeight; y++)
    {
        for (int x = 0; x < iWidth; x++)
        {
            
                    sf::IntRect Rect(tile[ iMapArray[y][x]]->iLeftKoord, tile[iMapArray[y][x]]->iTopKoord, tile[ iMapArray[y][x]]->iRightKoord, tile[iMapArray[y][x]]->iBottomKoord);
       
                    // Gefundener Wert in erstes Sprite schieben

                    dummySprite->SetSubRect(Rect);
                    dummySprite->SetPosition(m_fWidth *x + fXPos, m_fHeight* y+ fYPos);
                    esWindow->GetApp()->Draw(dummySprite)
        }
    }

Werbeanzeige