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

equinox

Frischling

  • »equinox« ist der Autor dieses Themas

Beiträge: 56

Beruf: Student

  • Private Nachricht senden

1

07.11.2013, 20:02

[XNA] Extrem langsames Zeichnen bei Isometrischer Karte(2D)

Hallo,

ich programmiere zurzeit ein kleines Spiel mit isometrischer Perspektive und habe dort extreme Geschwindigkeitsprobleme sobald ich eine spezielle Draw-Methode meiner Tiles aufrufe.

Gleich zu Beginn zurzeit zeichne ich noch über den sichtbaren Bereich hinaus, allerdings tritt das Problam auch bei knapp 30 Tiles auf.
Zur Struktur:
Ich habe ein 2D Array in meiner Kartenklasse, in der die Tiles gespeichert sind.
Die Tiles haben zurzeit ein Array der Größe 5 welches sogenannte Blöcke enthält. Diese dienen für Strukturen wie Gebäude, die aus einzelnen Blöcken zusammen gebaut werden.
(Zum Verständnis könnte man es als vereinfachte Voxel bezeichnen). Und genau dort liegt auch das Problem mit der Geschwindigkeit(siehe Draw Methode der Kartenklasse) und ich kann mir nicht erklären woher diese kommen.

Meine Map-Klasse(Auszugsweise)

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
class IsometricMap
    {
        Tile[,] tiles;
        public TileSet tileset;
        public Texture2D outdoor;
        public Texture2D indoor;
        const int _tilesize = 64;
        const int width = 39 ;
        const int height = 39 ;

        public SpriteFont font;

        //Konstruktor etc...
        
        
        public void Draw(SpriteBatch spriteBatch, Camera viewport)
        {
            int t = 0;
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {

                    Tile tmp = tiles[i, j];
                    
                    //Das was innerhalb des ersten If Blocks ausgeführt wird hängt unbeschreiblich, selbst wenn es nur ein Console.WriteLine ist
                    if (tmp.hasblocks) { spriteBatch.Draw(indoor, tmp.getPos(), tileset.getTile(tmp.getBlock(0).getTextureId()), Color.White); }
                    else if (j == testj && i == testi)
                    {
                        spriteBatch.Draw(outdoor, tmp.getPos(), tileset.getTile(tmp.getTextureID()), Color.Red);
                    }
                    else
                        spriteBatch.Draw(outdoor, tmp.getPos(), tileset.getTile(tmp.getTextureID()), Color.White);
                }
            }
        }
   
        public Tile getTileForPosition(Vector2 pos)
        { 
            
            Vector2 r1 = new Vector2(0, 0);
            Vector2 u1 = new Vector2(-32,16);
            Vector2 u2 = new Vector2(32, 16);

            //Projektion mithilfe von Geraden
            float v = (r1.X * u2.Y - pos.X * u2.Y - r1.Y * u2.X + pos.Y * u2.X) / (u2.Y * u2.X - u1.X * u2.Y);
            float t = (r1.X * u1.Y - pos.X * u1.Y - r1.Y * u1.X + pos.Y * u1.X) / (u1.Y * u1.X - u2.X * u1.Y);
          

            int x = (int)v;// (int)(p1.Length() / u1.Length());
            int y = (int)t;// (int)(p2.Length() / u2.Length());
            Console.WriteLine("Pos: " + pos.ToString() /*+ " :p->u1: " + p1.ToString() */+ " x: " + x /*+ "\n:p->u2: " + p2.ToString()*/ + " y: " + y + "\nv: " + v + " t: " + t);
            if (x >= 0 && x < width && y >= 0 && y < height)
                return tiles[y, x];
            return null;
        }
    }
}


Meine Tile-Klasse

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
class Tile
    {
        int texture_id;
        Vector2 position;
        Block[] blocks = new Block[5];

        //wird in einem setter auf true gesetzt
        public bool hasblocks = false;
        //Konstruktor u. getter/setter 
        
        public int getHeight(Vector2 pos)
        {
            if (blocks.Length == 0)
                return 0;
            int _height = blocks[0].getHeightForPos(pos);

            return _height;
        }
        public bool hasBlocks()
        {
            return hasblocks;
        }
    }


Meine Block-Klasse:

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
class Block
    {
        int texture_id;
        int z;
        int height;
        byte heightmap = 0x0F;
        Vector2 pos;
        //Tile parent;
        byte collision = 00000000;
       
        //Konstruktor u. Getter/Setter
      
        public int getHeightForPos(Vector2 pos)
        {
            if (heightmap == 0x0F)
                return height;
            if (heightmap == 0x00)
                return 0;
            Vector2 origin = this.pos;// parent.getPos();
            Vector2 r1 = new Vector2(0, 32) + origin;
            Vector2 u1 = new Vector2(-1, -1);
            Vector2 u2 = new Vector2(1, -1);
            u1.Normalize();
            u2.Normalize();
            float x = (r1.X * u2.Y - pos.X * u2.Y - r1.Y * u2.X + pos.Y * u2.X) / (u2.Y * u2.X - u1.X * u2.Y);
            float y = (r1.X * u1.Y - pos.X * u1.Y - r1.Y * u1.X + pos.Y * u1.X) / (u1.Y * u1.X - u2.X * u1.Y);
            float length = (float)Math.Sqrt(16 * 16 + 32 * 32);
            float alpha_tan = (float)height / (float)length;
            float dist = 0;

            switch (heightmap)
            {
                case 0x03:
                    dist = length - x;
                    break;
                case 0x05:
                    dist = length - y;
                    break;
                case 0x06:
                    dist = x;
                    break;
                case 0x0C:
                    dist = y;
                    break;
            }
            return (int)(dist * alpha_tan);
          
        }
    }


Die Draw Methode wird selbstverständlich in der Draw-Methode der Spielschleife aufgerufen.

Ich hoffe, dass das alles ausführlich genug ist damit mir jemand helfen kann.

Gruß,

equinox

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »equinox« (07.11.2013, 23:16)


equinox

Frischling

  • »equinox« ist der Autor dieses Themas

Beiträge: 56

Beruf: Student

  • Private Nachricht senden

2

07.11.2013, 23:29

Ich entschuldige mich schonmal für meinen Doppelpost, aber ich denke er macht thematisch Sinn:
Ich habe das Problem behoben, es lag an einem wegen einem Test im Code stehendem Console.WriteLine(...)

Kann mir mal jemand erklären warum soetwas so eine extreme Auswirkung hat?

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

3

08.11.2013, 10:28

Das liegt daran, dass die Ausführung deines Programms bei jeder Ausgabe solange blockiert bis die Ausgabe abgeschlossen ist. Da dies aber eine nicht unwesentliche Zeit in Anspruch nimmt erhöhst du die Gesamt Dauer um die Summe der Einzelzeiten bei der Ausgabe.

Auch wenn der Beitrag ein bisschen Thematisch abweicht enthält er neben Gezicke auch Erklärungen die deine Frage beantworten. Jedoch mit C++ beispielen, in diesem Fall aber unerheblich für die Aussage.
:love: := Go;

Werbeanzeige