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

08.08.2012, 15:23

SFML - 2 Dimensionales Array von Instanzen

Hallo,
ich habe eine Game-Klasse, die für das Rendern und so zuständig ist.
In der Methode LoadLevel() wird aus einem PNG ein Level geladen.
Dabei wird Pixel für Pixel in zwei ineinander verschachtelten For-Schleifen durchgegangen.
Dieser Pixel soll dann in seiner Farbe im Fenster gezeichnet werden.
Dafür habe ich die Klasse CBlock mit dem Konstruktor

C-/C++-Quelltext

1
CBlock(int XPos, int YPos, int Width, int Height, sf::Color Color)
der ein Shape erzeugt und das Shape in einer Membervariablen speichert.

Ziel ist es, in der LoadLevel-Fkt. per Array, Vektor, was auch immer, das Level zu laden,
sodass ich später mittels Index die Shapes ansprechen kann und auch Attribute für die Blöcke festlegen kann.

Nur wie erstelle ich Instanzen in einer Schleife?
Ich hab es so versucht, was natürlich nicht 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
// LoadLevel
//
void CGame::LoadLevel()
{
    sf::Image LevelImage;
    if (!LevelImage.LoadFromFile("Level/level.png"))
    {
        // Error...
    }

    CBlock Block[41][11]; 
    for(int i = 0; i < 40; i++)
    {
        for(int j = 0; j < 11; j++)
        {
            m_PixelColor[i][j] = LevelImage.GetPixel(i, j);
            Block[i][j](0, 0, 0, 0, m_PixelColor[i][j]);
        }
    }
    cout << "Level erfolgreich geladen." << endl;
} // LoadLevel


Fehlermeldung: "Ausdruck ergibt keine Funktion, die 5 Argumente übernimmt"

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

2

08.08.2012, 15:36

Ich bin mir nicht sicher, wie man es mit einem reinen Array macht, aber diese sollte man auch nur in Ausnahmefällen verwenden. Mit einem std::vector funktioniert das so:

C-/C++-Quelltext

1
std::vector<std::vector<CBlock> > Block(41, std::vector<CBlock>(11, CBlock(x, y, w, h, c)));
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

idontknow

unregistriert

3

08.08.2012, 15:56

Da ist übrigens auch dein Fehler, du hast als Konstruktor von "CBlock" "Block" benutzt (dein Array von CBlöcken). Wenn dann musst du ne Zuweisung machen ala Block[j] = CBlock(..); aber die Lösung von expl0it3r is defintiv besser.

4

08.08.2012, 16:14

Ok, danke.
Und wie bau ich das jetzt in die Header- und .cpp-Datei ein,
und wie greife ich auf die Elemete des Vectors zu?

Edit: Hier die Datein:


game.hpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

using namespace std;

class CGame
{
    public:
        CGame(sf::RenderWindow *Window);
        void Render();
        void LoadLevel();
        void DrawLevel();;
        void MoveView(int X, int Y);

    private:
        sf::RenderWindow *m_pApp;
        sf::Color m_PixelColor[40][11];
        sf::View LevelView;
};


game.cpp:

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
71
72
73
74
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

#include <iostream>
using namespace std;

#include "game.hpp"
#include "block.hpp"

// Konstruktor
//
CGame::CGame(sf::RenderWindow *Window)//(sf::RenderWindow &App)
{
    m_pApp = Window;
    LoadLevel();
    LevelView.SetFromRect(sf::FloatRect(0, 0, 800, 600));
    m_pApp->SetView(LevelView);
} // Konstruktor


// Render
//
void CGame::Render()//sf::RenderWindow &App)
{
    m_pApp->Clear(sf::Color::White);

    m_pApp->Draw(sf::Shape::Line(0, 550, 800, 550, 5, sf::Color::Black));

    DrawLevel();//App);

    m_pApp->Display();
} // Render


// LoadLevel
//
void CGame::LoadLevel()
{
    sf::Image LevelImage;
    if (!LevelImage.LoadFromFile("Level/level.png"))
    {
        // Error...
    }

    for(int i = 0; i < 40; i++)
    {
        for(int j = 0; j < 11; j++)
        {
            m_PixelColor[i][j] = LevelImage.GetPixel(i, j);
        }
    }
    cout << "Level erfolgreich geladen." << endl;
} // LoadLevel

// DrawLevel
//
void CGame::DrawLevel()//(sf::RenderWindow &App)
{
    for(int i = 0; i < 40; i++)
    {
        for(int j = 0; j < 11; j++)
        {
            //Block[i][j].Render(m_pApp);
            //m_pApp->Draw(sf::Shape::Rectangle(i*50, j*50, i*50+50, j*50+50, m_PixelColor[i][j]));
        }
    }
} // DrawLevel

// MoveView
//
void CGame::MoveView(int X, int Y)
{
    LevelView.Move(X, Y);
} // MoveView


block.hpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

class CBlock
{
    public:
        CBlock();
        CBlock(int XPos, int YPos, int Width, int Height, sf::Color Color);

        void Render(sf::RenderWindow *App);

        int GetXPos();
        int GetYPos();

    private:
        sf::Shape m_Rect;
        int m_XPos;
        int m_YPos;
        int m_Width;
        int m_Height;
};


block.cpp:

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
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

#include <iostream>
#include <string>
using namespace std;

#include "block.hpp"

// Konstruktor: CBlock
//
CBlock::CBlock()
{
    
} // Konstruktor: CBlock


// Konstruktor: CBlock(int XPos, int YPos, int Width, int Height, sf::Color Color)
// 
CBlock::CBlock(int XPos, int YPos, int Width, int Height, sf::Color Color)
{
    //m_Counter++;

    m_XPos = XPos;
    m_YPos = YPos;
    m_Width = Width;
    m_Height = Height;
    m_Rect = sf::Shape::Rectangle(m_XPos, m_YPos, m_XPos+m_Width, m_YPos+m_Height, Color);
    cout << "Instanz der Klasse CBlock mit den Parametern " << m_XPos << ", " << m_YPos << ", " << m_Width << ", " << m_Height << Color.r << "," << Color.g << "," << Color.b << " erzeugt" << endl; 

} // Konstruktor: CBlock(int XPos, int YPos, int Width, int Height, sf::Color Color)


// Render
//
void CBlock::Render(sf::RenderWindow *App)
{
    App->Draw(m_Rect);
} // Render


// GetX
//
int CBlock::GetXPos()
{
    return m_XPos;
} // GetX


// GetY
//
int CBlock::GetYPos()
{
    return m_YPos;
} // GetY

idontknow

unregistriert

5

08.08.2012, 16:17

Auf die Elemente des Vectors kannst du zugreifen wie auf die Elemente eines Arrays. Das klappt, weil std::vector den [] operator überlädt. Der Vektor ist nur ein dynamisches Array, dass sich automatisch vergrößert/verkleinert.

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

6

08.08.2012, 16:18

Naja das solltest du jetzt eigentlich selbst herausfinden können, das sind C++ Grundlagen, wenn dir da noch etwas Wissen fehlt, dann empfehle ich dir dies mit einem Buch nachzuholen. ;)

In die Header Datei schreibst du einfach:

C-/C++-Quelltext

1
std::vector<std::vector<CBlock> > Block;

In die Source Datei:

C-/C++-Quelltext

1
Block(41, std::vector<CBlock>(11, CBlock(x, y, w, h, c)));

Und Zugriff auf die Elemente erhälst du wie bei einem Array mit dem [] Operator:

C-/C++-Quelltext

1
Block[0][0];
oder Alternative

C-/C++-Quelltext

1
Block.at(0).at(0);
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

7

08.08.2012, 16:18

Das Problem ist ja die Aufteilung in 2 Klassen, aber kann ich den Vektor irgendwie als Membervariable von CGame definieren,
da CGame den CBlock ja nicht kennt?
Ein Include der block.hpp führt zur Typneudefinition oder so.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Nathax« (08.08.2012, 16:30)


eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

8

08.08.2012, 16:34

Das Problem ist ja die Aufteilung in 2 Klassen, aber kann ich den Vektor irgendwie als Membervariable von CGame definieren,
da CGame den CBlock ja nicht kennt?
Ein Include der block.hpp führt zur Typneudefinition oder so.

Was?

Du hast CBlock und nimmst dies als Membervariabel von CGame, damit CGame weiss was CBlock ist, musst du einfach die Header Datei von CBlock in der Header Datei von CGame inkludieren.
Um Typen Neudefinitionen zu verhindern, musst du include-guards verwenden, z.B.:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef CGAME_HPP
#define CGAME_HPP

#include "CBlock.hpp"

class CGame
{
private:
    std::vector<std::vector<CBlock> > m_Block;
    // ...
};

#endif // CGAME_HPP
Dies ist überigends eine weitere Grundlage von C++, welche ein gutes Buch erklären würde. ;)
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

9

08.08.2012, 19:39

Das Problem ist ja die Aufteilung in 2 Klassen, aber kann ich den Vektor irgendwie als Membervariable von CGame definieren,
da CGame den CBlock ja nicht kennt?
Ein Include der block.hpp führt zur Typneudefinition oder so.

Was?

Du hast CBlock und nimmst dies als Membervariabel von CGame, damit CGame weiss was CBlock ist, musst du einfach die Header Datei von CBlock in der Header Datei von CGame inkludieren.
Um Typen Neudefinitionen zu verhindern, musst du include-guards verwenden, z.B.:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef CGAME_HPP
#define CGAME_HPP

#include "CBlock.hpp"

class CGame
{
private:
    std::vector > m_Block;
    // ...
};

#endif // CGAME_HPP
Dies ist überigends eine weitere Grundlage von C++, welche ein gutes Buch erklären würde. ;)
Ich hab das Buch von Heiko Kalista (C++ für Spieleprogrammierer) und soweit ich weiß werden include-guards dort nicht wirklich behandelt.
Natürlich weiß ich, dass ich die .hpp einfach includen muss, aber wie gesagt, da kam halt der von mir geschilderte Fehler, den ich trotz dem,
dass ich das meiste im Buch angesprochene beherrsche, nicht beheben konnte, weil eben die Guards dort nicht behandelt wurden.
Vielen dank, dass du mich aufgeklärt hast. Hab mich schon gewundert was das ist, was so viele Leute immer in die Headerdatein schreiben. :)

Edit: Folgende Zeile aus der game.cpp fürht bei mir zum Fehler:

C-/C++-Quelltext

1
m_Block(41, vector<CBlock>(11, CBlock(0, 0, 0, 0, sf::Color::Black)));


"Ausdruck ergibt keine Funktion, die 2 Argumente übernimmt"

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Nathax« (08.08.2012, 19:52)


10

08.08.2012, 19:51

Vielleicht auch schon früher, weil es nicht so gut erläutert, aber erwähnt ist, blättere mal auf Seite 236 und lies dort nach dem ersten Absatz Text.
Irre ich mich oder werden "diese komischen Dinger" da wirklich erwähnt? :search:
Nebenbei: Der Typ heißt Heiko Kalista, steht ja sogar in Großbuchstaben da, jedenfalls der Nachname. Wie man da das A am Ende mit einem O verwechseln kann, das ist mir doch ein wenig schleierhaft.

MfG
Check

Werbeanzeige