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