Hallo liebe Spieleprogrammierer!
Habe kürzlich ein neues Projekt begonnen und bin grade dabei, erstmal die grundlegenden Klassen dafür fertig zu machen.
Diese habe ich bis jetzt alle so oder ähnlich bereits verwendet, weshalb sich mir auch der Grund für genannte Zugriffsverletzung völlig entschließt. :/
Ich habe eine Klasse CSprite, deren Instanzen jeweils eine Grafik vertreten sollen, welche folgendermaßen aussieht und eigentlich super funktioniert:
|
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
|
class CSprite
{
public:
CSprite();
~CSprite();
void Load(const string sFilename);
void Load(const string sFilename, int NumFrames,
int FrameWidth, int FrameHeight);
void LoadNew();
void SetColorKey(int R, int G, int B);
void SetPos(float fXPos, float fYPos);
void Render();
void Render(float fFrameNumber);
SDL_Rect GetRect() { return m_Rect; }
private:
SDL_Renderer *m_pRenderer; // Zeiger auf die Textur des Frameworks
SDL_Surface *m_pImage; // Das eigentliche Bild des Sprites
SDL_Texture *m_pTexture; // Textur für die Surface
SDL_Rect m_Rect; // Rect des Sprites
SDL_Rect m_FrameRect; // Ausschnitt für Animationsphase
int m_NumFrames; // Anzahl der Animationsphasen
int m_FrameWidth; // Breite einer Animationsphase
int m_FrameHeight; // Höhe einer Animationsphase
int m_NumFramesX; // Wie viele Anim-Phasen in X-Richtung?
};
|
|
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
|
// Konstruktor
//
// Aufgabe: Zeiger auf Renderer holen und Membervariablen initialisieren
//
CSprite::CSprite() : m_pImage(nullptr), m_pTexture(nullptr)// Zeiger erstmal auf NULL setzen
{
cout << "Konstruktor (Sprite) wurde aufgerufen!" << endl;
// Zeiger auf Renderer holen
m_pRenderer = g_pFramework->GetRenderer();
} // Konstruktor
// Load
//
// Aufgabe: Einfaches, nicht animiertes Sprite laden
//
void CSprite::Load(const string sFilename)
{
// Surface freigeben, falls es bereits genutzt wurde
if (m_pImage != nullptr)
SDL_FreeSurface(m_pImage);
// Bilddatei laden
m_pImage = IMG_Load(sFilename.c_str());
// Prüfen, ob alles glatt ging
if (m_pImage == nullptr)
{
[...]
}
// Rect initialisieren
m_Rect.x = 0;
m_Rect.y = 0;
m_Rect.w = m_pImage->w;
m_Rect.h = m_pImage->h;
} // Load
// Render
//
// Aufgabe: Sprite rendern (ohne Animation)
//
void CSprite::Render()
{
// Ist Textur noch leer?
if (m_pTexture == nullptr)
{
// Ja, also Surface in Textur speichern
m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, m_pImage);
cout << "Surface wurde in Textur gespeichert!" << endl;
}
// Textur rendern
SDL_RenderCopy(m_pRenderer, m_pTexture, nullptr, &m_Rect);
} // Render
|
Diese Klasse Sprite wird in eine Klasse CButton eingebunden, welche zwei Sprites speichert, um bei MouseOver die Grafik wechseln zu können. Diese Klasse scheint irgendwie Probleme zu machen, denn wie man später im Code der Main sehen wird, sind Sprites zu rendern kein Problem. Das Problem kommt mit dieser Klasse:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class CButton
{
public:
void Init(const string sFilenameActive, const string sFilenamePassive,
int xPos, int yPos);
void Render();
const SDL_Rect &GetRect(){ return m_ButtonRect; }
void SetActive(bool bActive){ m_bActive = bActive; }
private:
CSprite m_SpriteButtonActive; // Sprite für den "aktiven" Button
CSprite m_SpriteButtonPassive; // Sprite für den "passiven" Button
SDL_Rect m_ButtonRect; // Rect für den Button
bool m_bActive; // Button aktiv oder passiv?
};
|
|
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
|
// Init
//
// Aufgabe: Button initialisieren
//
void CButton::Init(const string sFilenameActive, const string sFilenamePassive,
int xPos, int yPos)
{
cout << "init" << endl;
// Sprite für aktiven und passiven Zustand des Buttons laden
m_SpriteButtonActive.Load(sFilenameActive);
m_SpriteButtonPassive.Load(sFilenamePassive);
cout << "loaded" << endl;
// Positionen der Buttons setzen
m_SpriteButtonActive.SetPos(xPos, yPos);
m_SpriteButtonPassive.SetPos(xPos, yPos);
// Rect initialisieren
m_ButtonRect.x = xPos;
m_ButtonRect.y = yPos;
m_ButtonRect.w = m_SpriteButtonActive.GetRect().w;
m_ButtonRect.h = m_SpriteButtonActive.GetRect().h;
// erstmal auf passiv setzen
m_bActive = false;
// Pink zu Transparenz
m_SpriteButtonActive.SetColorKey(255, 0, 255);
m_SpriteButtonPassive.SetColorKey(255, 0, 255);
} // Init
// Render
//
// Aufgabe: Button rendern
//
void CButton::Render()
{
if (m_bActive)
m_SpriteButtonActive.Render();
else
m_SpriteButtonPassive.Render();
} // Render
|
Hier werden der Init-Funktion zwei Dateipfade übergeben, mit deren Hilfe die beiden Sprites durch die CSprite::Load() Funktion geladen werden können.
Ich füge noch die Main.cpp an um dann zur genaueren Beschreibung des Problems zu kommen:
|
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
|
//Nur das wichtige aus der Main:
//
CSprite Sprite_Background;
Sprite_Background.Load("Data/Graphics/Malen_nach_Zahlen/BackgroundBMP.bmp");
CSprite Sprite_Test;
Sprite_Test.Load("Data/Graphics/Malen_nach_Zahlen/TestPNG.png");
CSprite Sprite_Button;
Sprite_Button.Load("Data/Graphics/Back_Button_Passive.png");
Sprite_Button.SetPos(400, 400);
CButton Button_Test;
Button_Test.Init("Data/Graphics/Back_Button_Active.png", "Data/Graphics/Back_Button_Passive.png", 500, 400);
Button_Test.SetActive(true);
CMenu MainMenu;
MainMenu.LoadButton("Play", Button_Test);
while (1 == 1)
{
g_pFramework->Clear();
Sprite_Background.Render();
Sprite_Test.Render();
Sprite_Button.Render();
Button_Test.Render();
g_pFramework->Flip();
}
|
Die Main besteht zur Zeit nur zu experimentellen Zwecken sei dazu gesagt, also meckert bitte nicht, wie sie aussieht
Da die Sprites bis Zeile 26 (Button_Test.Render()) beim Debugger kein Problem machen, sondern erst genannter Button, schließe ich, dass es sich um einen Fehler in CButton handeln muss, aber ich habe wirklich keine Idee, welcher das sein könnte..
Der Debugger springt von Button_Test.Render() in die entspr. Funkiton "Render" aus CSprite und hält dort bei Zeile 54 an mit einer Zugriffsverletzung :/
Hoffe irgendwer blickt da durch und kann mir helfen
Danke,
Tim