Membervariablen in andere Klassen tragen

aaron2005

Grünschnabel
Ich habe leider nichts hilfreiches gefunden zu meinen Problem.
Ich versuche mich am SDK (was hier glaube weniger die Rolle spielt) und habe anhand eines Tutorials Grafik auf den Bildschirm zu zaubern. Nun hab ich die Idee eines Break out Spiels. Wobei es mir jetzt erstmal darum geht möglichst einfach die Klötzchen auf den Bildschirm zu verteilen.

Ich kann die Steine zwar verteilen aber nur mit im Renderer vordefinierten Werten...

Ich poste am besten mal den wichtigen Code und erkläre währenddessen meine Probleme.

Die Stein.h
Code:
class C_Stein
{
    int m_HP;
    //Position des Steines
    int m_X;
    int m_Y;

    //Aussehen des Steines durch Tileset
    int m_X2;
    int m_Y2;
    int m_h;
    int m_b;
    //Wird gebraucht um die Art des Steines festzulegen
    int m_Sorte;

    public:

    C_Stein();
    void init(int X, int Y, int Sorte);

};

Die Stein.cpp

Code:
#include <iostream>
#include "CSprite.h"
#include "Stein.h"


C_Stein::C_Stein()
{

}

void C_Stein::init(int X, int Y, int Sorte)
{
    //Ist die halbe Länge eines steines, um ohne viel Rechnerei Steine nebeneinander zu legen
    X *= 25;
    Y *= 20;

    m_X = X;
    m_Y = Y;

    //Bestimmt über das Aussehen des Steines
    switch (Sorte)
    {
        case 1:
        {
            m_X2 = 0;
            m_Y2 = 0;
            m_h = 50;
            m_b = 25;
        }break;
...
    }

}


Das dient als Vorbereitung auf die Levelklasse.

Level.h
Code:
ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED

class C_Level
{
    public:
    void init();

};

#endif // LEVEL_H_INCLUDED

und Level.cpp

Code:
#include <iostream>
#include "Stein.h"
#include "Level.h"

void init(int L)
{
    switch (L)
    {
        //Je nach Level werden die Anzahl der Steine und die Parameter geändert
        case 1:
        {

            C_Stein Stein[10];
            Stein[0].init(0, 0, 1);
            Stein[1].init(0, 0, 1);
            Stein[2].init(0, 0, 1);
            Stein[3].init(0, 0, 1);
            Stein[4].init(0, 0, 1);
            Stein[5].init(0, 0, 1);
            Stein[6].init(0, 0, 1);
            Stein[7].init(0, 0, 1);
            Stein[8].init(0, 0, 1);
            Stein[9].init(0, 0, 1);
            Stein[10].init(0, 0, 1);
        }
    }


}
Es sei gesagt dass weitere case Fälle folgen, jedes Level ein Case. Über Sinn und Unsinn der per #include eingefügten Dateien sei mal dahin gestellt.

Soweit so gut. Das ganze ist erstmal so gedacht, dass ich dem Array von "Stein" verschiedene Werte zukommen lasse. Die Spalte, danach die Reihe und zuletzt die Sorte. Die oberen Werte werden nach ersten Erfolgen geändert.

Nun ist mein Problem dass ich die m_x und m_y Werte der Stein[] Instanzen nicht in folgende Funktion bekomme:

Code:
#include "CApp.h"
#include "CSprite.h"
#include "Stein.h"
#include "Level.h"

void CApp::OnRender()
{

    for (int i = 0; i <= 10; i++ )
    {
        CSurface::OnDraw(Surf_Display, Surf_Stein[i], 100, 100 + (i * 20), 50, 0, 50, 25);

        //Stein[i]->m_X
    }


    SDL_Flip(Surf_Display);

}

die Stelle im Kommentar soll zum Beispiel am ersten 100er angehangen werden (dieses i * 20 war nur zur Probe ob ich mehrere Steine erstellen kann und ja ich kann^^)

Genauer gesagt, kennt er die Instanz Stein[] nicht und ich wüsste spontan auch nicht, wie ich das Problem mit Zeiger lösen könnte.

Ich hoffe, ich habe alles mitgegeben für eine Lösung, ansonsten sagt an, was fehlt.

Zur CSprite.h bzw. CSprite.cpp sei gesagt, dass dort die die Prototypen von den SDL Surfaces lauern
 
Hi

SDK? Welches?

Stein.h:
Wenn du schon einen public-Bereich hast,
schadet private oder protected für den anderen doch auch nicht.

Und das ifndef-define-endif wie in der Level.h könnte man hier doch auch machen.

Level.cpp:
Verwende doch Schleifen!
C++:
for(int i = 0; i < 11; i++)
    Stein[i].init(0, 0, 1);

Du rufst da init für 11 Steine auf.
Es gibt aber nur 10.
Folge: Kann man so schwer sagen.
aber wenn du einen ganz unerklärlichen Fehler feststellst,
ist die Stelle ein potenzieller Verursacher.

Die Zeile
C++:
C_Stein Stein[10];
ist innerhalb von case 1.
Folge: Am Ende vom case werden alle Steine wieder gelöscht.
Unter anderem deswegen bekommst du sie auch nicht in CApp rein.

Schreib init so um, dass es zum int L dazu einen zweiten Parameter bekommt,
und zwar das Steinarray. Dafür eben nicht im case erzeugen.
Dann im private/protected-Bereich von CApp ein Steinarray machen
und an geeigneter Stelle die init-Funktion aufrufen.

Gruß
 
@Sheel. Erstmal danke für die Antwort.

Das mit der Schleife wird erstmal nichts, da diese ganze Reihe von Stein[ i ].init erstmal Testweise ist und jeder Stein eben an einer anderen Stelle steht, also (0, 0, 1) (2, 0, 1) usw. Das mit der zusätzlichen Zahl wegen 0 hab ich dabei gerade verdrängt^^

Ok, ich schau mal wie ich das gelöst kriege^^ Danke für den Tip.

Das mit dem protected bereich war ich erstmal zu faul gewesen, da ja unkommentierte Klassen erstmal private sind.

Wegen den ifndef usw. muss ich ehrlich sagen, dass ich bisher keine Verwendung drin gefunden habe (bzw. Sinn)...
 
Wenn du include´s nicht nur in cpp, sondern auch in h-Dateien verwendest
(was nötig wird, wenn der Code wächst) gibt es Situationen,
wo eine h-Datei mehrfach inkludiert werden sollte.

zB. wenn die Level.h Stein.h inkludiert, inkludiert die Level.cpp
Level.h, dadurch Stein.h und dann nocheinmal Stein.h

Ohne den ifndef... gibts dann Probleme, weil zweimal derselbe Code abgearbeitet wird.
Mit den selben Klassen/Variablennamen usw.

Mit ifndef... wird es nur einmal gemacht, egal wie oft es inkludiert wird.
 
Genauer gesagt, kennt er die Instanz Stein[] nicht
Wie auch. Das Array "Stein" war nur mal irgendwann lokal auf dem Stack in der Funktion init erzeugt und ist dann auch gleich wieder weggeräumt worden.

Du könntest es ja z.B. so machen:
C++:
class C_Level {
   int level;
   C_Stein* config;
   void init(int);
   C_Level(const C_Level&) /* = delete */;

public:
  C_Level(): level(1), config(0) {
     init(level);
  }
   ~C_Level() {
     delete[] config;
     config = 0;
  }

  void operator++() {
    init(++level);
  }
  void operator(int) {
    ++(*this);
  }
};

void C_Level::init(int level) {
   delete[] config;
   config = new C_Stein[...];

   switch (level) {
    ...
   }
}
Du brauchst natürlich auch noch getter für die Attribute die öffentlich sein sollen.

Gruß
 
Zuletzt bearbeitet:
Und wieder muss ich stören -.-

Folgendes hat sich geändert.
Die Capp.h

Code:
#ifndef _CAPP_H_
#define _CAPP_H_

#include <SDL.h>
#include "Stein.h"

class CApp {

    private:

    C_Stein Stein[10];

    bool running;

    SDL_Surface* Surf_Display;

    SDL_Surface*    Surf_Stein[10];

    public:

        CApp();

        int OnExecute();

        bool OnInit();
        void OnEvent(SDL_Event *Event);
        void OnLoop();
        //void OnRender();
        int OnRender(C_Stein Stein[]); // <-- Das
        void OnCleanup();

};

#endif


Die CApp.cpp
Code:
   while (running)
    {
        while (SDL_PollEvent(&Event))
        {
            OnEvent(&Event);
        }

        OnLoop();
        //OnRender();
        OnRender(Stein); <-- Das

    }
    OnCleanup();

Level.cpp
Code:
void init(int L, C_Stein Stein[])
{

            Stein[0].init(0, 0, 1);
            Stein[1].init(0, 0, 1);
            Stein[2].init(0, 0, 1);
            Stein[3].init(0, 0, 1);
            Stein[4].init(0, 0, 1);
            Stein[5].init(0, 0, 1);
            Stein[6].init(0, 0, 1);
            Stein[7].init(0, 0, 1);
            Stein[8].init(0, 0, 1);
            Stein[9].init(0, 0, 1);
            Stein[10].init(0, 0, 1);

    switch (L)
    {
        //Je nach Level werden die Anzahl der Steine und die Parameter geändert
        case 1:
        {



        }
    }


}
Ich habe die Instanzerstellung der Steine in die Capp gepackt und die init Zuweisung testweise außerhalb der Cases gemacht.

Level.h
Code:
class C_Level
{
    public:
    void init(int L, C_Stein Stein[]);

};

Dazu hab ich das Array in die Parameter gesteckt

OnRender.cpp
Code:
int CApp::OnRender(C_Stein Stein[])
{

    for (int i = 0; i <= 10; i++ )
    {
        CSurface::OnDraw(Surf_Display, Surf_Stein[i], m_X, 100 + (i * 30), 50, 0, 50, 25);

        //&Stein::m_X
    }


    SDL_Flip(Surf_Display);

}


Und eine Funktion dem Parameter des Klassenarrays umgebaut. Ich kann zwar indem ich bei der haupt CApp.cpp den hier benutze: OnRender(Stein);
Auf diese Funktion zugreifen, nur hab ich keine Ahnung, wie ich jetzt aus dem übergebenen Klassenarray die Membervariable raus fische. Ich habe es mit Stein[i]::m_X versucht (daraufhin er sagt:

Code:
\CApp_OnRender.cpp|11|error: expected ')' before '::' token|
\CApp_OnRender.cpp|11|error: no matching function for call to 'CSurface::OnDraw(SDL_Surface*&, SDL_Surface*&, C_Stein&, int, int, int, int, int)'|
bei Stein[i]->m_X kommt das.
Code:
CApp_OnRender.cpp|11|error: base operand of '->' has non-pointer type 'C_Stein'|

weitere Möglichkeiten in die Instanz zu gehen weiß ich gerade nicht. Und ich bin mir irgendwie auch unsicher ob meine Stein.init zugeschlagen haben.
 
Du rufst da init für 11 Steine auf.
Es gibt aber nur 10.
Du musst 11 anlegen.

Und wie deepthroat schon schrieb, für Zugriff auf m_x muss es entweder public sein
oder es gibt eine Getter-Funktion
C++:
int get_m_X()
{
    return m_X;
}

Der richtige Zugriff in OnRender:
C++:
Stein[i].get_m_X()
oder, ohne Getter
C++:
Stein[i].m_X
 
Und wie deepthroat schon schrieb, für Zugriff auf m_x muss es entweder public sein
oder es gibt eine Getter-Funktion
C++:
int get_m_X()
{
    return m_X;
}
Das m_ ist nur ein Präfix für Attribute, das wird nicht in den Namen des Getters übernommen. Und const fehlt:
C++:
int get_X() const {
  return m_X;
}
Gruß
 
Das mit dem Punkt hatte ich nicht durchdacht :-(

jetzt komm ich denke mal auch Weiter : D


UNd wegen den 11 Steine aufrufen und nur 10 Steine haben.
Da ich überall ein Array von [10] habe, hab ich doch auch 11 Steine :confused:
auch bei der Instanzerstellung C_Stein Stein[10] hab ich meine Steinchen von 0 - 10 = 11 oder hab ich da was nicht mitbekommen

das Public wär erstmal meine erste Variante wenigstens um zu Testen.

Code:
int get_X() const {
  return m_X;
}
Das heißt ich darf für jeden Stein 6 mal solch eine Funktion durchlaufen? (X, Y, X2, Y2, H, B)
Ganz doofe Frage... an welcher Stelle soll ich die Funktionen einbauen?
 

Neue Beiträge

Zurück